marty 1.0.1 → 1.0.3

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.
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