mochigome 0.1.9 → 0.1.10

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/lib/mochigome.rb CHANGED
@@ -4,6 +4,7 @@ require 'model_extensions'
4
4
  require 'model_graph'
5
5
  require 'data_node'
6
6
  require 'query'
7
+ require 'relation'
7
8
  require 'formatting'
8
9
  require 'subgroup_model'
9
10
  require 'arel_rails2_hacks'
data/lib/mochigome_ver.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mochigome
2
- VERSION = "0.1.9"
2
+ VERSION = "0.1.10"
3
3
  end
data/lib/query.rb CHANGED
@@ -187,138 +187,4 @@ module Mochigome
187
187
  end
188
188
  end
189
189
  end
190
-
191
- private
192
-
193
- class Relation
194
- attr_reader :joins, :spine_layers
195
-
196
- def initialize(layers)
197
- @model_graph = ModelGraph.new
198
- @spine_layers = layers
199
- @models = Set.new
200
- @spine = []
201
- @joins = []
202
-
203
- @spine_layers.map(&:to_real_model).uniq.each do |m|
204
- if @rel
205
- join_to_model(m)
206
- else
207
- @rel = @model_graph.relation_init(m)
208
- @models.add m
209
- end
210
- @spine << m
211
- end
212
- @spine_layers.each{|m| select_model_id(m)}
213
- end
214
-
215
- def to_arel
216
- @rel.clone
217
- end
218
-
219
- def to_sql
220
- @rel.to_sql
221
- end
222
-
223
- def clone
224
- c = super
225
- c.instance_variable_set :@models, @models.clone
226
- c.instance_variable_set :@rel, @rel.clone
227
- c
228
- end
229
-
230
- def join_to_model(model)
231
- return if @models.include?(model)
232
-
233
- # Route to it in as few steps as possible, closer to spine end if tie.
234
- best_path = nil
235
- (@spine.reverse + (@models.to_a - @spine)).each do |link_model|
236
- path = @model_graph.path_thru([link_model, model])
237
- if path && (best_path.nil? || path.size < best_path.size)
238
- best_path = path
239
- end
240
- end
241
-
242
- raise QueryError.new("No path to #{model}") unless best_path
243
- join_on_path(best_path)
244
-
245
- # TODO: Write a test that requires the below code to work
246
- @models.reject{|n| best_path.include?(n)}.each do |n|
247
- cond = @model_graph.edge_condition(n, model)
248
- if cond
249
- @rel = @rel.where(cond)
250
- end
251
- end
252
- end
253
-
254
- def join_on_path_thru(path)
255
- full_path = @model_graph.path_thru(path).uniq
256
- if full_path
257
- join_on_path(full_path)
258
- else
259
- raise QueryError.new("Cannot route thru #{path.map(&:name).inspect}")
260
- end
261
- end
262
-
263
- def join_on_path(path)
264
- path = path.map(&:to_real_model).uniq
265
- join_to_model path.first
266
- (0..(path.size-2)).map{|i| [path[i], path[i+1]]}.each do |src, tgt|
267
- add_join_link(src, tgt) unless @models.include?(tgt)
268
- end
269
- end
270
-
271
- def select_model_id(m)
272
- @rel = @rel.project(m.arel_primary_key.as("#{m.name}_id"))
273
- end
274
-
275
- def select_expr(e)
276
- @model_graph.expr_models(e).each{|m| join_to_model(m)}
277
- @rel = @rel.project(e)
278
- end
279
-
280
- def apply_condition(cond)
281
- return unless cond
282
- if cond.is_a?(ActiveRecord::Base)
283
- cond = [cond]
284
- end
285
- if cond.is_a?(Array)
286
- # TODO: Should group by type and use IN expressions
287
- cond = cond.inject(nil) do |expr, obj|
288
- subexpr = obj.class.arel_primary_key.eq(obj.id)
289
- expr ? expr.or(subexpr) : subexpr
290
- end
291
- end
292
-
293
- @model_graph.expr_models(cond).each{|m| join_to_model(m)}
294
- @rel = @rel.where(cond)
295
- end
296
-
297
- def apply_access_filter_func(func)
298
- @models.each do |m|
299
- h = func.call(m)
300
- h.delete(:join_paths).try :each do |path|
301
- join_on_path path
302
- end
303
- if h[:condition]
304
- apply_condition h.delete(:condition)
305
- end
306
- unless h.empty?
307
- raise QueryError.new("Unknown assoc filter keys #{h.keys.inspect}")
308
- end
309
- end
310
- end
311
-
312
- private
313
-
314
- def add_join_link(src, tgt)
315
- raise QueryError.new("Can't join from #{src}, not available") unless
316
- @models.include?(src)
317
- @rel = @rel.join(tgt.arel_table, Arel::Nodes::InnerJoin).on(
318
- @model_graph.edge_condition(src, tgt)
319
- )
320
- @models.add tgt
321
- @joins << [src, tgt]
322
- end
323
- end
324
190
  end
data/lib/relation.rb ADDED
@@ -0,0 +1,141 @@
1
+ module Mochigome
2
+ private
3
+
4
+ class Relation
5
+ attr_reader :joins, :spine_layers
6
+
7
+ def initialize(layers)
8
+ @model_graph = ModelGraph.new
9
+ @spine_layers = layers
10
+ @models = Set.new
11
+ @spine = []
12
+ @joins = []
13
+
14
+ @spine_layers.map(&:to_real_model).uniq.each do |m|
15
+ if @rel
16
+ join_to_model(m)
17
+ else
18
+ @rel = @model_graph.relation_init(m)
19
+ @models.add m
20
+ end
21
+ @spine << m
22
+ end
23
+ @spine_layers.each{|m| select_model_id(m)}
24
+ end
25
+
26
+ def to_arel
27
+ @rel.clone
28
+ end
29
+
30
+ def to_sql
31
+ @rel.to_sql
32
+ end
33
+
34
+ def clone
35
+ c = super
36
+ c.instance_variable_set :@models, @models.clone
37
+ c.instance_variable_set :@rel, @rel.clone
38
+ c
39
+ end
40
+
41
+ def join_to_model(model)
42
+ return if @models.include?(model)
43
+
44
+ # Route to it in as few steps as possible, closer to spine end if tie.
45
+ best_path = nil
46
+ (@spine.reverse + (@models.to_a - @spine)).each do |link_model|
47
+ path = @model_graph.path_thru([link_model, model])
48
+ if path && (best_path.nil? || path.size < best_path.size)
49
+ best_path = path
50
+ end
51
+ end
52
+
53
+ raise QueryError.new("No path to #{model}") unless best_path
54
+ join_on_path(best_path)
55
+
56
+ # Also use the conditions of any other direct assoc to the target
57
+ # TODO: Or maybe any other assoc that's equal length?
58
+ # TODO: Write a test that requires the below code to work
59
+ @models.reject{|n| best_path.include?(n)}.each do |n|
60
+ cond = @model_graph.edge_condition(n, model)
61
+ if cond
62
+ @rel = @rel.where(cond)
63
+ end
64
+ end
65
+ end
66
+
67
+ def join_on_path_thru(path)
68
+ full_path = @model_graph.path_thru(path).uniq
69
+ if full_path
70
+ join_on_path(full_path)
71
+ else
72
+ raise QueryError.new("Cannot route thru #{path.map(&:name).inspect}")
73
+ end
74
+ end
75
+
76
+ def join_on_path(path)
77
+ path = path.map(&:to_real_model).uniq
78
+ join_to_model path.first
79
+ (0..(path.size-2)).map{|i| [path[i], path[i+1]]}.each do |src, tgt|
80
+ add_join_link(src, tgt) unless @models.include?(tgt)
81
+ end
82
+ end
83
+
84
+ def select_model_id(m)
85
+ @rel = @rel.project(m.arel_primary_key.as("#{m.name}_id"))
86
+ end
87
+
88
+ def select_expr(e)
89
+ join_to_expr_models(e)
90
+ @rel = @rel.project(e)
91
+ end
92
+
93
+ def apply_condition(cond)
94
+ return unless cond
95
+ if cond.is_a?(ActiveRecord::Base)
96
+ cond = [cond]
97
+ end
98
+ if cond.is_a?(Array)
99
+ # TODO: Should group by type and use IN expressions
100
+ cond = cond.inject(nil) do |expr, obj|
101
+ subexpr = obj.class.arel_primary_key.eq(obj.id)
102
+ expr ? expr.or(subexpr) : subexpr
103
+ end
104
+ end
105
+
106
+ join_to_expr_models(cond)
107
+ @rel = @rel.where(cond)
108
+ end
109
+
110
+ def apply_access_filter_func(func)
111
+ @models.each do |m|
112
+ h = func.call(m)
113
+ h.delete(:join_paths).try :each do |path|
114
+ join_on_path path
115
+ end
116
+ if h[:condition]
117
+ apply_condition h.delete(:condition)
118
+ end
119
+ unless h.empty?
120
+ raise QueryError.new("Unknown assoc filter keys #{h.keys.inspect}")
121
+ end
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def add_join_link(src, tgt)
128
+ raise QueryError.new("Can't join from #{src}, not available") unless
129
+ @models.include?(src)
130
+ @models.add tgt
131
+ cond = @model_graph.edge_condition(src, tgt)
132
+ join_to_expr_models(cond)
133
+ @rel = @rel.join(tgt.arel_table, Arel::Nodes::InnerJoin).on(cond)
134
+ @joins << [src, tgt]
135
+ end
136
+
137
+ def join_to_expr_models(expr)
138
+ @model_graph.expr_models(expr).each{|m| join_to_model(m)}
139
+ end
140
+ end
141
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mochigome
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 9
10
- version: 0.1.9
9
+ - 10
10
+ version: 0.1.10
11
11
  platform: ruby
12
12
  authors:
13
13
  - David Mike Simon
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-16 00:00:00 Z
18
+ date: 2012-05-17 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement
@@ -113,6 +113,7 @@ files:
113
113
  - lib/model_extensions.rb
114
114
  - lib/model_graph.rb
115
115
  - lib/query.rb
116
+ - lib/relation.rb
116
117
  - lib/subgroup_model.rb
117
118
  - test/app_root/app/controllers/application_controller.rb
118
119
  - test/app_root/app/controllers/report_controller.rb