marty 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77e6182b8e9feb509b401e87c0fd8233bfa6777a
4
- data.tar.gz: 78707cf573b3c33d872b0346a4751c38f26f14d3
3
+ metadata.gz: bebe74227eb431e5b56683fb41cdf571d65ad9ae
4
+ data.tar.gz: 52e50bf586ade69e69501f408ba8795d5296a108
5
5
  SHA512:
6
- metadata.gz: 7ca495f675cbe04547f2d885a6661f1da7cc6793bf7c9fc9a55759e24b4877df7878a032347dd3c0d81b5c5122b8cc504d47ed0560cdd2bd73ea8e0a51ece0d4
7
- data.tar.gz: 1898fd8cd7daf7d3e7d2d0f8ed8560a45c7874339b2617291f782d005910a0d6ab8c3b68d5630c32521a597bfc27883737c4b28552a08745675742f144e5367e
6
+ metadata.gz: 6f047a2e07c4c2808c7385e7558e9c1243710e62385f317a7ab472175f78e22fb4fd74119d3d30b5cb2117d0ee3e7b834f6077e1ab463b9df887dae4f28c6632
7
+ data.tar.gz: 68b1e9630134ac55a561a3e9b4df22ac4e7dc0fd6bbc43fcb032ec505c4e98c70c4a521c368d317267a5687569ab851eff8b4861ca53a273afda14f89e1d153d
@@ -42,9 +42,11 @@ class Marty::AuthApp < Marty::SimpleApp
42
42
  if user
43
43
  Netzke::Base.controller.set_user(user)
44
44
  client.netzke_set_result(true)
45
+ true
45
46
  else
46
47
  client.netzke_set_result(false)
47
48
  client.netzke_notify("Wrong credentials")
49
+ false
48
50
  end
49
51
  end
50
52
 
@@ -128,7 +128,7 @@ class Marty::PromiseView < Netzke::Tree::Base
128
128
 
129
129
  endpoint :clear do |params|
130
130
  Marty::Promise.cleanup(true)
131
- client.on_refresh
131
+ client.netzke_on_refresh
132
132
  end
133
133
 
134
134
  def get_records params
@@ -41,7 +41,7 @@
41
41
  },
42
42
 
43
43
  netzkeLoadComponentByAction: function(action){
44
- this.router.add(action.name);
44
+ this.router.add(action.name.underscore());
45
45
  },
46
46
 
47
47
  onToggleConfigMode: function(params){
@@ -147,13 +147,11 @@ class Marty::DataGrid < Marty::Base
147
147
  data_type.constantize rescue nil
148
148
  end
149
149
 
150
- def lookup_grid_distinct(pt, h, return_grid_data=false, distinct=true)
151
- isets = {}
152
-
153
- (dir_infos("v") + dir_infos("h")).each do
154
- |inf|
150
+ def query_grid_dir(h, infos)
151
+ return [0] if infos.empty?
155
152
 
156
- dir, type, attr = inf["dir"], inf["type"], inf["attr"]
153
+ sqla = infos.map do |inf|
154
+ type, attr = inf["type"], inf["attr"]
157
155
 
158
156
  next unless h.has_key?(attr)
159
157
 
@@ -161,6 +159,8 @@ class Marty::DataGrid < Marty::Base
161
159
 
162
160
  ix_class = INDEX_MAP[type] || INDEX_MAP["string"]
163
161
 
162
+ q = "key IS NULL"
163
+
164
164
  unless v.nil?
165
165
  q = case type
166
166
  when "boolean"
@@ -169,7 +169,7 @@ class Marty::DataGrid < Marty::Base
169
169
  "key @> ?"
170
170
  else # "string", "integer", AR klass
171
171
  "key @> ARRAY[?]"
172
- end
172
+ end + " OR #{q}"
173
173
 
174
174
  # FIXME: very hacky -- need to cast numrange/intrange values or
175
175
  # we get errors from PG.
@@ -185,34 +185,35 @@ class Marty::DataGrid < Marty::Base
185
185
  else # AR class
186
186
  v.to_s
187
187
  end
188
-
189
- ixa = ix_class.
190
- where(data_grid_id: group_id,
191
- created_dt: created_dt,
192
- attr: inf["attr"],
193
- ).
194
- where(q, v).uniq.pluck(:index)
195
188
  end
196
189
 
197
- if v.nil? || ixa.empty?
198
- ixa = ix_class.
199
- where(data_grid_id: group_id,
200
- created_dt: created_dt,
201
- attr: inf["attr"],
202
- key: nil,
203
- ).uniq.pluck(:index)
204
- end
190
+ # FIXME: could potentially order results by key NULLS LAST.
191
+ # This would prefer more specific rather than wild card
192
+ # solutions. However, would need to figure out how to preserve
193
+ # ordering on subsequent INTERSECT operations.
194
+ ixq = ix_class.
195
+ select(:index).
196
+ distinct.
197
+ where(data_grid_id: group_id,
198
+ created_dt: created_dt,
199
+ attr: inf["attr"],
200
+ ).
201
+ where(q, v).to_sql
202
+ end.compact
205
203
 
206
- # FIXME: optimization: bail out if one of the sets is empty.
207
- # Or, even better, we should submit all the queris together.
208
- isets[dir] = isets[dir] ? isets[dir] & ixa : Set.new(ixa)
209
- end
204
+ sql = sqla.join(" INTERSECT ")
205
+
206
+ self.class.connection.execute(sql).to_a.map { |h| h["index"].to_i }
207
+ end
208
+
209
+ def lookup_grid_distinct(pt, h, return_grid_data=false, distinct=true)
210
+ isets = ["h", "v"].each_with_object({}) do |dir, isets|
211
+ infos = dir_infos(dir)
210
212
 
211
- ["h", "v"].each do |dir|
212
- isets[dir] = Set[0] if !isets[dir] && dir_infos(dir).empty?
213
+ isets[dir] = query_grid_dir(h, infos)
213
214
 
214
215
  unless isets[dir] or return_grid_data
215
- attrs = dir_infos(dir).map { |inf| inf["attr"] }
216
+ attrs = infos.map { |inf| inf["attr"] }
216
217
 
217
218
  raise "#{dir} attrs not provided: %s" % attrs.join(',')
218
219
  end
@@ -221,7 +222,8 @@ class Marty::DataGrid < Marty::Base
221
222
  distinct && isets[dir] && isets[dir].count > 1
222
223
  end
223
224
 
224
- vi, hi = isets["v"].first, isets["h"].first if isets["v"] && isets["h"]
225
+ # deterministic result: pick min index when there's a choice
226
+ vi, hi = isets["v"].min, isets["h"].min if isets["v"] && isets["h"]
225
227
 
226
228
  raise "DataGrid lookup failed #{name}" unless (vi && hi) or lenient or
227
229
  return_grid_data
@@ -343,29 +345,22 @@ class Marty::DataGrid < Marty::Base
343
345
  meta_rows = dt_row.empty? ? [] : [dt_row]
344
346
 
345
347
  meta_rows += metadata.map { |inf|
346
- [
347
- inf["attr"],
348
- inf["type"],
349
- inf["dir"],
350
- inf["rs_keep"] || "",
351
- ]
348
+ [inf["attr"], inf["type"], inf["dir"], inf["rs_keep"] || ""]
352
349
  }
353
350
 
354
351
  v_infos, h_infos = dir_infos("v"), dir_infos("h")
355
352
 
356
- h_key_rows = h_infos.map do
357
- |inf|
358
-
353
+ h_key_rows = h_infos.map { |inf|
359
354
  [nil]*v_infos.count + self.class.export_keys(inf)
360
- end
355
+ }
361
356
 
362
357
  transposed_v_keys = v_infos.empty? ? [[]] :
363
358
  v_infos.map {|inf| self.class.export_keys(inf)}.transpose
364
359
 
365
- data_rows = transposed_v_keys.each_with_index.map do
366
- |keys, i|
360
+ data_rows = transposed_v_keys.each_with_index.map { |keys, i|
367
361
  keys + (self.data[i] || [])
368
- end
362
+ }
363
+
369
364
  [meta_rows, h_key_rows, data_rows]
370
365
  end
371
366
 
@@ -460,8 +455,12 @@ class Marty::DataGrid < Marty::Base
460
455
  raise "must have a blank row separating metadata" unless
461
456
  blank_index
462
457
 
463
- data_type = nil
464
- lenient = false
458
+ raise "can't import grid with trailing blank column" if
459
+ rows.map { |r| r.last.nil? }.all?
460
+
461
+ raise "last row can't be blank" if rows[-1].all?(&:nil?)
462
+
463
+ data_type, lenient = nil, false
465
464
 
466
465
  # check if there's a data_type definition
467
466
  dt, *x = rows[0]
@@ -661,10 +660,10 @@ class Marty::DataGrid < Marty::Base
661
660
 
662
661
  def opposite_sign(op) # toggle sign and inclusivity
663
662
  {
664
- lt: :ge,
665
- le: :gt,
666
- gt: :le,
667
- ge: :lt,
663
+ :< => :>=,
664
+ :<= => :>,
665
+ :> => :<=,
666
+ :>= => :<,
668
667
  }[op]
669
668
  end
670
669
 
@@ -682,35 +681,35 @@ class Marty::DataGrid < Marty::Base
682
681
  lhv, rhv = orig_lhv || -Float::INFINITY, orig_rhv || Float::INFINITY
683
682
 
684
683
  case op
685
- when :ge, :gt
684
+ when :>=, :>
686
685
  next if value > rhv
687
686
 
688
687
  if value == rhv
689
- if rhop == :le && op == :ge
688
+ if rhop == :<= && op == :>=
690
689
  rewrite_a.push(
691
- [index, rewrite_range(lhop, orig_lhv, orig_rhv, :lt)])
690
+ [index, rewrite_range(lhop, orig_lhv, orig_rhv, :<)])
692
691
  end
693
692
  elsif value > lhv
694
693
  rewrite_a.push(
695
694
  [index, rewrite_range(lhop, orig_lhv, value, opposite_sign(op))])
696
- elsif value == lhv && lhop == :ge && op == :gt
697
- rewrite_a.push([index, rewrite_range(:ge, value, value, :le)])
695
+ elsif value == lhv && lhop == :>= && op == :>
696
+ rewrite_a.push([index, rewrite_range(:>=, value, value, :<=)])
698
697
  elsif value <= lhv
699
698
  prune_a.push(index)
700
699
  end
701
- when :le, :lt
700
+ when :<=, :<
702
701
  next if value < lhv
703
702
 
704
703
  if value == lhv
705
- if lhop == :ge && op == :le
704
+ if lhop == :>= && op == :<=
706
705
  rewrite_a.push(
707
- [index, rewrite_range(:gt, orig_lhv, orig_rhv, rhop)])
706
+ [index, rewrite_range(:>, orig_lhv, orig_rhv, rhop)])
708
707
  end
709
708
  elsif value < rhv
710
709
  rewrite_a.push(
711
710
  [index, rewrite_range(opposite_sign(op), value, orig_rhv, rhop)])
712
- elsif value == rhv && rhop == :le && op == :lt
713
- rewrite_a.push([index, rewrite_range(:ge, value, value, :le)])
711
+ elsif value == rhv && rhop == :<= && op == :<
712
+ rewrite_a.push([index, rewrite_range(:>=, value, value, :<=)])
714
713
  elsif value >= rhv
715
714
  prune_a.push(index)
716
715
  end
@@ -753,18 +752,18 @@ class Marty::DataGrid < Marty::Base
753
752
  lhv = lhs.blank? ? nil : lhs.to_f
754
753
  rhv = rhs.blank? ? nil : rhs.to_f
755
754
 
756
- [lboundary == '(' ? :gt : :ge, lhv, rhv, rboundary == ')' ? :lt : :le]
755
+ [lboundary == '(' ? :> : :>=, lhv, rhv, rboundary == ')' ? :< : :<=]
757
756
  end
758
757
 
759
758
  def rewrite_range(lb, lhv, rhv, rb)
760
- lboundary = lb == :gt ? '(' : '['
759
+ lboundary = lb == :> ? '(' : '['
761
760
 
762
761
  # even though numranges are float type, we don't want to output ".0"
763
762
  # for integer values. So for values like that we convert to int
764
763
  # first before conversion to string
765
764
  lvalue = (lhv.to_i == lhv ? lhv.to_i : lhv).to_s
766
765
  rvalue = (rhv.to_i == rhv ? rhv.to_i : rhv).to_s
767
- rboundary = rb == :lt ? ')' : ']'
766
+ rboundary = rb == :< ? ')' : ']'
768
767
  lboundary + lvalue + ',' + rvalue + rboundary
769
768
  end
770
769
 
@@ -774,16 +773,8 @@ class Marty::DataGrid < Marty::Base
774
773
 
775
774
  opstr, ident = match[1..2]
776
775
 
777
- orig_op = {
778
- '<' => :lt,
779
- '>' => :gt,
780
- '<=' => :le,
781
- '>=' => :ge,
782
- '' => :inc,
783
- }[opstr]
784
-
785
776
  # data grid value is expressed as what to keep
786
777
  # we convert to the opposite (what to prune)
787
- [opposite_sign(orig_op), ident]
778
+ [opposite_sign(opstr.to_sym), ident]
788
779
  end
789
780
  end
data/lib/marty/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.3"
3
3
  end
@@ -127,6 +127,25 @@ n\tnumrange\tv
127
127
  true\t1\t<10\t<10.0\tY
128
128
  \t2\t\t\tM
129
129
  false\t\t>10\t\tN
130
+ EOS
131
+
132
+ Gg = <<EOS
133
+ lenient
134
+ i1\tinteger\tv
135
+ i2\tinteger\tv
136
+
137
+ \t1\t1
138
+ 2\t1\t21
139
+ 2\t\t20
140
+ EOS
141
+
142
+ Gh = <<EOS
143
+ lenient
144
+ property_state\tstring\tv
145
+ county_name\tstring\tv
146
+
147
+ NY\t\t10
148
+ \tR\t8
130
149
  EOS
131
150
 
132
151
  before(:each) do
@@ -140,6 +159,20 @@ EOS
140
159
  [res["result"], res["name"]]
141
160
  end
142
161
 
162
+ describe "imports" do
163
+ it "should not allow imports with trailing blank columns" do
164
+ expect {
165
+ dg_from_import("G1", G1.gsub("\n", "\t\n"))
166
+ }.to raise_error(RuntimeError)
167
+ end
168
+
169
+ it "should not allow imports with last blank row" do
170
+ expect {
171
+ dg_from_import("Gh", Gh+"\t\t\n")
172
+ }.to raise_error(RuntimeError)
173
+ end
174
+ end
175
+
143
176
  describe "validations" do
144
177
  it "a basic data grid should load ok" do
145
178
  dg_from_import("G1", G1)
@@ -223,7 +256,7 @@ EOS
223
256
 
224
257
  before(:each) do
225
258
  ["G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "Ga", "Gb",
226
- "Gc", "Gd", "Ge", "Gf"].each { |g|
259
+ "Gc", "Gd", "Ge", "Gf", "Gg", "Gh"].each { |g|
227
260
  dg_from_import(g, "Marty::DataGridSpec::#{g}".constantize)
228
261
  }
229
262
  end
@@ -232,32 +265,27 @@ EOS
232
265
  let(:dg) { Marty::DataGrid.lookup(pt, "Gf") }
233
266
 
234
267
  it 'true returns Y' do
235
- res = Marty::DataGrid.
236
- lookup_grid(pt, dg, {"b"=>true}, true)
268
+ res = Marty::DataGrid.lookup_grid(pt, dg, {"b"=>true}, false)
237
269
  expect(res).to eq('Y')
238
270
  end
239
271
 
240
272
  it '13 returns N' do
241
- res = Marty::DataGrid.
242
- lookup_grid(pt, dg, {"i"=>13}, true)
273
+ res = Marty::DataGrid.lookup_grid(pt, dg, {"i"=>13}, true)
243
274
  expect(res).to eq('N')
244
275
  end
245
276
 
246
277
  it '13 & numrange 0 returns nil' do
247
- res = Marty::DataGrid.
248
- lookup_grid(pt, dg, {"i"=>13, "n"=>0}, true)
249
- expect(res).to be_nil
278
+ res = Marty::DataGrid.lookup_grid(pt, dg, {"i"=>13, "n"=>0}, true)
279
+ expect(res).to eq('N')
250
280
  end
251
281
 
252
282
  it '13 & int4range 15 returns N' do
253
- res = Marty::DataGrid.
254
- lookup_grid(pt, dg, {"i"=>13, "i4"=>15}, true)
283
+ res = Marty::DataGrid.lookup_grid(pt, dg, {"i"=>13, "i4"=>15}, true)
255
284
  expect(res).to eq('N')
256
285
  end
257
286
 
258
287
  it '13 & int4range 1 returns nil' do
259
- res = Marty::DataGrid.
260
- lookup_grid(pt, dg, {"i"=>13, "i4"=>1}, true)
288
+ res = Marty::DataGrid.lookup_grid(pt, dg, {"i"=>13, "i4"=>1}, true)
261
289
  expect(res).to be_nil
262
290
  end
263
291
 
@@ -268,12 +296,38 @@ EOS
268
296
  end
269
297
 
270
298
  it '13, numrange 15 returns N' do
271
- res = Marty::DataGrid.
272
- lookup_grid(pt, dg, {"i"=>13, "n"=>15}, true)
299
+ res = Marty::DataGrid.lookup_grid(pt, dg, {"i"=>13, "n"=>15}, true)
273
300
  expect(res).to eq('N')
274
301
  end
275
302
  end
276
303
 
304
+ it "should handle ambiguous lookups" do
305
+ dg = Marty::DataGrid.lookup(pt, "Gh")
306
+
307
+ h1 = {
308
+ "property_state" => "NY",
309
+ "county_name" => "R",
310
+ }
311
+
312
+ res = Marty::DataGrid.lookup_grid(pt, dg, h1, false)
313
+ expect(res).to eq(10)
314
+ end
315
+
316
+ it "should handle ambiguous lookups (2)" do
317
+ dg = Marty::DataGrid.lookup(pt, "Gg")
318
+ res = Marty::DataGrid.
319
+ lookup_grid(pt, dg, {"i1"=>2, "i2"=>1}, false)
320
+ expect(res).to eq(1)
321
+
322
+ res = Marty::DataGrid.
323
+ lookup_grid(pt, dg, {"i1"=>3, "i2"=>1}, false)
324
+ expect(res).to eq(1)
325
+
326
+ res = Marty::DataGrid.
327
+ lookup_grid(pt, dg, {"i1"=>2, "i2"=>3}, false)
328
+ expect(res).to eq(20)
329
+ end
330
+
277
331
  it "should handle non-distinct lookups" do
278
332
  dg = Marty::DataGrid.lookup(pt, "Ge")
279
333
  res = Marty::DataGrid.lookup_grid(pt, dg, {"ltv"=>500}, false)
@@ -372,11 +426,12 @@ EOS
372
426
  it "should handle matches which also have a wildcard match" do
373
427
  dg_from_import("G9", G9)
374
428
 
375
- res = lookup_grid_helper('infinity',
376
- "G9",
377
- {"state" => "CA", "ltv" => 81},
378
- )
379
- expect(res).to eq [123,"G9"]
429
+ expect {
430
+ res = lookup_grid_helper('infinity',
431
+ "G9",
432
+ {"state" => "CA", "ltv" => 81},
433
+ )
434
+ }.to raise_error(RuntimeError)
380
435
 
381
436
  res = lookup_grid_helper('infinity',
382
437
  "G9",
@@ -449,7 +504,8 @@ EOS
449
504
  end
450
505
 
451
506
  it "should handle DataGrid typed data grids" do
452
- expect(Marty::DataGrid.lookup('infinity', "G8").data_type).to eq "Marty::DataGrid"
507
+ expect(Marty::DataGrid.lookup('infinity', "G8").data_type).
508
+ to eq "Marty::DataGrid"
453
509
  g1 = Marty::DataGrid.lookup('infinity', "G1")
454
510
 
455
511
  res = lookup_grid_helper('infinity',
@@ -461,7 +517,8 @@ EOS
461
517
  end
462
518
 
463
519
  it "should handle multi DataGrid lookups" do
464
- expect(Marty::DataGrid.lookup('infinity', "G8").data_type).to eq "Marty::DataGrid"
520
+ expect(Marty::DataGrid.lookup('infinity', "G8").data_type).
521
+ to eq "Marty::DataGrid"
465
522
  g1 = Marty::DataGrid.lookup('infinity', "G1")
466
523
 
467
524
  h = {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marty
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2016-06-20 00:00:00.000000000 Z
17
+ date: 2016-07-14 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: pg