mongoid-report 0.1.9 → 0.2.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.
@@ -10,8 +10,12 @@ module Mongoid
10
10
  end
11
11
 
12
12
  def scopes
13
- @scopes ||= modules.map do |key|
14
- Scope.new(context, key)
13
+ @scopes ||= [].tap do |collection|
14
+ context.settings.each do |report_module, module_settings|
15
+ module_settings[:reports].each do |report_name, _report_settings|
16
+ collection << Scope.new(context, report_module, report_name)
17
+ end
18
+ end
15
19
  end
16
20
  end
17
21
 
@@ -29,31 +33,33 @@ module Mongoid
29
33
  self
30
34
  end
31
35
 
36
+ def in_batches(conditions)
37
+ scopes.each do |scope|
38
+ scope.in_batches(conditions)
39
+ end
40
+ self
41
+ end
42
+
32
43
  def all
33
- {}.tap do |hash|
44
+ Hash.new { |h, k| h[k] = {} }.tap do |hash|
34
45
  if Mongoid::Report::Config.use_threads_on_aggregate
35
46
  scopes.map do |scope|
36
47
  Thread.new do
37
48
  rows = scope.all
38
49
 
39
50
  @mutex.synchronize do
40
- hash[scope.report_name] = rows
51
+ hash[scope.report_module][scope.report_name] = rows
41
52
  end
42
53
  end
43
54
  end.map(&:join)
44
55
  else
45
56
  scopes.each do |scope|
46
- hash[scope.report_name] = scope.all
57
+ hash[scope.report_module][scope.report_name] = scope.all
47
58
  end
48
59
  end
49
60
  end
50
61
  end
51
62
 
52
- private
53
-
54
- def modules
55
- context.settings.keys
56
- end
57
63
  end
58
64
 
59
65
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Report
3
- VERSION = "0.1.9"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -5,6 +5,11 @@ require_relative 'report/config'
5
5
  require_relative 'report/queries_builder'
6
6
  require_relative 'report/attach_proxy'
7
7
  require_relative 'report/collection'
8
+ require_relative 'report/batches'
9
+ require_relative 'report/merger'
10
+ require_relative 'report/collections'
11
+ require_relative 'report/output'
12
+ require_relative 'report/input'
8
13
  require_relative 'report/scope'
9
14
  require_relative 'report/scope_collection'
10
15
  require_relative 'report/report_proxy'
@@ -18,46 +23,116 @@ module Mongoid
18
23
 
19
24
  class_attribute :settings
20
25
 
26
+ # TODO: rewrite this module adding clone method for the all settings
27
+ # defined for the mongoid-report. for now it's creating the duplicates.
28
+ # check out the mongoid library for the best example.
21
29
  self.settings = {}
22
30
 
23
31
  def self.inherited(subclass)
24
- subclass.settings = self.settings.dup
32
+ subclass.settings = {}
25
33
  end
26
34
 
27
35
  # Variable for copying internal class settings to the instance because of
28
- # possible modifications in case of using filters with lambda
36
+ # possible modifications in case of using maches with lambda
29
37
  # expressions.
30
38
  attr_reader :report_module_settings
31
39
 
32
40
  def initialize_report_module
33
41
  # Lets store settings under created instance.
34
- @report_module_settings = self.class.settings.dup
42
+ @report_module_settings = self.settings.inject({}) do |hash_module, (report_module, module_settings)|
43
+ hash_module.merge!(
44
+ report_module =>
45
+ {
46
+ fields: module_settings[:fields],
47
+ group_by: module_settings[:group_by],
48
+ batches: module_settings[:batches],
49
+ columns: module_settings[:columns],
50
+ mapping: module_settings[:mapping],
51
+ queries: (module_settings[:queries] || []).dup,
52
+ reports: (module_settings[:reports] || {}).inject({}) do |hash_report, (report_name, report_settings)|
53
+ hash_report.merge!(
54
+ report_name => {
55
+ collection: report_settings[:collection],
56
+ fields: report_settings[:fields],
57
+ group_by: report_settings[:group_by],
58
+ batches: report_settings[:batches],
59
+ columns: report_settings[:columns],
60
+ mapping: report_settings[:mapping],
61
+ queries: (report_settings[:queries] || []).dup,
62
+ })
63
+ end
64
+ })
65
+ end
66
+
67
+ @report_module_settings.each do |report_module, module_configuration|
68
+ # Lets do not run queries builder in case of missing queries or group
69
+ # by parameters
70
+ unless module_configuration[:queries].empty? && module_configuration[:group_by].empty?
71
+ builder = QueriesBuilder.new(module_configuration)
72
+
73
+ # Prepare group queries depends on the configuration in the included
74
+ # class.
75
+ queries = builder.do
35
76
 
36
- @report_module_settings.each do |klass, configuration|
37
- builder = QueriesBuilder.new(configuration)
77
+ # Now we have access to compiled queries to run it in aggregation
78
+ # framework.
79
+ module_configuration[:queries] = module_configuration[:queries] + queries
80
+ end
81
+
82
+ # For now we are filtering by $match queries only.
83
+ matches = module_configuration[:queries].select do |query|
84
+ query['$match'].present?
85
+ end
38
86
 
39
- # Prepare group queries depends on the configuration in the included
40
- # class.
41
- @queries = builder.do
87
+ module_configuration[:reports].each do |report_name, report_configuration|
88
+ # Lets merge report and module settings together.
89
+ report_configuration[:fields] = report_configuration[:fields] | module_configuration[:fields]
90
+ report_configuration[:group_by] = report_configuration[:group_by] | module_configuration[:group_by]
91
+ report_configuration[:columns] = report_configuration[:columns].merge(module_configuration[:columns])
92
+ report_configuration[:mapping] = report_configuration[:mapping].merge(module_configuration[:mapping])
42
93
 
43
- # Now we have access to compiled queries to run it in aggregation
44
- # framework.
45
- configuration[:queries].concat(@queries)
94
+ builder = QueriesBuilder.new(report_configuration)
95
+
96
+ # Prepare group queries depends on the configuration in the included
97
+ # class.
98
+ queries = builder.do
99
+
100
+ # Now we have access to compiled queries to run it in aggregation
101
+ # framework.
102
+ report_configuration[:queries] = report_configuration[:queries] + matches + queries
103
+ end
46
104
  end
47
105
  end
48
106
  alias :initialize :initialize_report_module
49
107
 
50
- def queries(klass)
51
- report_module_settings[klass][:queries]
108
+ def queries(report_module, report_name)
109
+ report_module_settings[report_module][:reports][report_name][:queries]
110
+ end
111
+
112
+ def mapping(report_module, report_name)
113
+ report_module_settings[report_module][:reports][report_name][:mapping]
52
114
  end
53
115
 
54
- def mapping(klass)
55
- report_module_settings[klass][:mapping]
116
+ def batches(report_module, report_name)
117
+ report_module_settings[report_module][:reports][report_name][:batches]
56
118
  end
57
119
 
58
- # We should pass here mongoid document
59
- def aggregate_for(report_name)
60
- Scope.new(self, report_name)
120
+ def groups(report_module, report_name)
121
+ report_module_settings[report_module][:reports][report_name][:group_by]
122
+ end
123
+
124
+ def fields(report_module, report_name)
125
+ report_module_settings[report_module][:reports][report_name][:fields]
126
+ end
127
+
128
+ def columns(report_module, report_name)
129
+ report_module_settings[report_module][:reports][report_name][:columns]
130
+ end
131
+
132
+ # Method for preparing of aggregation scope where you can apply query,
133
+ # yield and other grouping methods.
134
+ def aggregate_for(report_module, report_name)
135
+ Scope.new(self, report_module, report_name)
61
136
  end
62
137
 
63
138
  def aggregate
@@ -71,14 +146,27 @@ module Mongoid
71
146
  proxy.instance_eval(&block)
72
147
  end
73
148
 
74
- def attach_to(collection, options = {}, &block)
75
- proxy = AttachProxy.new(self, collection, options)
76
- proxy.instance_eval(&block)
149
+ def attach_to(*fields, &block)
150
+ options = fields.extract_options!
151
+ collection = fields[0]
152
+
153
+ options.merge!(report_name: options[:as]) if options[:as]
154
+
155
+ define_report_method(options.merge(collection: collection)) do
156
+ proxy = AttachProxy.new(self, collection, options)
157
+ proxy.instance_eval(&block)
158
+ end
77
159
  end
78
160
 
79
- def filter(*fields)
80
- define_report_method(*fields) do |_, report_name, options|
81
- queries = self.settings_property(report_name, :queries)
161
+ def batches(*fields)
162
+ define_report_method(*fields) do |_, report_module, report_name, batches|
163
+ self.set_settings(report_module, report_name, :batches, batches.stringify_keys!)
164
+ end
165
+ end
166
+
167
+ def match(*fields)
168
+ define_report_method(*fields) do |_, report_module, report_name, options|
169
+ queries = self.get_settings(report_module, report_name, :queries)
82
170
 
83
171
  options.each do |key, value|
84
172
  queries
@@ -89,51 +177,62 @@ module Mongoid
89
177
  end
90
178
  end
91
179
 
180
+ def query(*fields)
181
+ define_report_method(*fields) do |_, report_module, report_name, options|
182
+ queries = self.get_settings(report_module, report_name, :queries)
183
+
184
+ options.each do |key, value|
185
+ queries.concat([{ key => value }])
186
+ end
187
+ end
188
+ end
189
+
92
190
  def group_by(*fields)
93
- define_report_method(*fields) do |groups, report_name, _|
94
- settings[report_name][:group_by] = groups.map(&:to_s)
191
+ define_report_method(*fields) do |groups, report_module, report_name, _|
192
+ self.set_settings(report_module, report_name, :group_by, groups.map(&:to_s))
95
193
  end
96
194
  end
97
195
 
98
196
  def column(*fields)
99
- define_report_method(*fields) do |columns, report_name, options|
100
- columns.each do |column|
101
- name = options.fetch(:as) { column }
102
- add_field(report_name, column, name)
197
+ define_report_method(*fields) do |columns, report_module, report_name, _|
198
+ columns.each do |field|
199
+ self.get_settings(report_module, report_name, :fields) << field.to_s
103
200
  end
104
201
  end
105
202
  end
106
203
 
107
204
  def columns(*fields)
108
- define_report_method(*fields) do |_, report_name, columns|
109
- self.settings[report_name][:columns] = columns.stringify_keys!
205
+ define_report_method(*fields) do |_, report_module, report_name, columns|
206
+ self.set_settings(report_module, report_name, :columns, columns.stringify_keys!)
110
207
  end
111
208
  end
112
209
 
113
210
  def mapping(*fields)
114
- define_report_method(*fields) do |_, report_name, mapping|
211
+ define_report_method(*fields) do |_, report_module, report_name, mapping|
115
212
  mapping.stringify_keys!
116
213
 
117
214
  mapping.each do |key, value|
118
215
  mapping[key] = value.to_s
119
216
  end
120
217
 
121
- self.settings[report_name][:mapping] = mapping
218
+ self.set_settings(report_module, report_name, :mapping, mapping)
122
219
  end
123
220
  end
124
221
 
125
- def fields(collection)
126
- settings_property(collection, :fields, {})
127
- end
128
-
129
- def groups(collection)
130
- settings_property(collection, :group_by, [])
222
+ def get_settings(report_module, report_name, field)
223
+ unless report_name
224
+ self.settings[report_module][field]
225
+ else
226
+ self.settings[report_module][:reports][report_name][field]
227
+ end
131
228
  end
132
229
 
133
- def settings_property(collection, key, default = [])
134
- settings
135
- .fetch(collection) { {} }
136
- .fetch(key) { default }
230
+ def set_settings(report_module, report_name, field, value)
231
+ unless report_name
232
+ self.settings[report_module][field] = value
233
+ else
234
+ self.settings[report_module][:reports][report_name][field] = value
235
+ end
137
236
  end
138
237
 
139
238
  private
@@ -142,38 +241,58 @@ module Mongoid
142
241
  options = fields.extract_options!
143
242
 
144
243
  # We should always specify model to attach fields, groups
145
- collection = options.fetch(:for)
146
- options.delete(:for)
244
+ collection = options.fetch(:collection)
245
+ options.delete(:collection)
246
+
247
+ # In case if user passed mongoid model we should get name of collection
248
+ # instead of using mongoid models. on deep_dup operations it will work
249
+ # find with strings.
250
+ collection = Collections.name(collection)
147
251
 
148
- # If user didn't pass as option to name the report we are using
149
- # collection class as key for settings.
150
- attach_name = options.fetch(:attach_name) { collection }
151
- options.delete(:attach_name)
252
+ report_module = options.delete(:report_module)
253
+ report_module ||= self.name
254
+
255
+ report_name = options.delete(:report_name)
256
+ report_name ||= Collections.name(collection)
152
257
 
153
258
  # We should always have for option
154
- initialize_settings_by(attach_name, collection)
259
+ initialize_settings_by(report_module, report_name, collection)
155
260
 
156
261
  # Because of modifying fields(usign exract options method of
157
262
  # ActiveSupport) lets pass fields to the next block with collection.
158
- yield fields, attach_name, options || {}
263
+ yield fields, report_module, report_name, options || {}
159
264
  end
160
265
 
161
- def initialize_settings_by(attach_name, collection)
162
- settings[attach_name] ||= settings.fetch(attach_name) do
266
+ def initialize_settings_by(report_module, report_name, collection)
267
+ # Global settings for the report block
268
+ settings[report_module] ||= settings.fetch(report_module) do
163
269
  {
164
- for: collection,
165
- fields: ActiveSupport::OrderedHash.new,
270
+ reports: {},
271
+ fields: [],
166
272
  group_by: [],
167
- queries: [],
273
+ batches: {},
168
274
  columns: {},
169
275
  mapping: {},
170
- compiled: false,
276
+ # needs to be cloned
277
+ queries: [],
171
278
  }
172
279
  end
173
- end
174
280
 
175
- def add_field(attach_name, field, name)
176
- settings[attach_name][:fields][field.to_s] = name.to_s
281
+ return unless report_name
282
+
283
+ settings[report_module][:reports][report_name] ||=
284
+ settings[report_module][:reports].fetch(report_name) do
285
+ {
286
+ collection: collection,
287
+ fields: [],
288
+ group_by: [],
289
+ batches: {},
290
+ columns: {},
291
+ mapping: {},
292
+ # needs to be cloned
293
+ queries: [],
294
+ }
295
+ end
177
296
  end
178
297
  end
179
298