mochigome 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
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