marty 1.2.2 → 1.2.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: 6ce8e00805092bcb838e01a7f27fb452f9c4302c
4
- data.tar.gz: '08ba3a7fae36b08f7503b3da6f9ee298161c146b'
3
+ metadata.gz: 4869432086cbb253966cbb6dc2b723bf3e1e39fb
4
+ data.tar.gz: 60ed80fcbf3f7ba5c28d6d8178fd0756f3fa241d
5
5
  SHA512:
6
- metadata.gz: 263d011eb1c69a38e68449ad6b2031f8f529bc3c89b166ba033d3cd4243b111357601142f8d362a5eb4aa4d72c065cb9531920e4564fbd4217a5c287bce25bd7
7
- data.tar.gz: 994794315f3c2e50222bc70c354e4feb1f9fbac4a7af4a476e2aeef99ab1a001bbbe289db72277b8d870c83bf68a934829d938d0eed187cc341334bde5f71737
6
+ metadata.gz: c05a246f66a03be87ee1a9ae7ba9ab45044716a12a05b9ca5268e370f23898650596ed4380989bb6a33719d3beb2576d70d3c292a9af18a4f6f2fca80bd79fa1
7
+ data.tar.gz: e2d7751ee36906871b524a13a9888571ab18eb35dc678d131505f84c6c559a8bbb27ac8cf8881b675f61af220b665d7b2d863e56d6e8b35643c56305f8114bc5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- marty (1.2.2)
4
+ marty (1.2.3)
5
5
  axlsx (= 2.1.0pre)
6
6
  coderay
7
7
  delorean_lang (~> 0.3.33)
@@ -58,17 +58,6 @@ class Marty::BaseRule < Marty::Base
58
58
  res_err = results.delete("~~ERROR~~")
59
59
  errors[:computed] <<
60
60
  "- Error in rule '#{name}' field 'results': #{res_err.capitalize}" if res_err
61
-
62
- same_name_diff_guards = self.class.
63
- where(obsoleted_dt: 'infinity', name: self.name).
64
- # id is nil on new rules
65
- where.not(id: self.id).
66
- where("simple_guards != '#{self.simple_guards.to_json}'")
67
-
68
- errors[:base] =
69
- "Can't have rule with same name and different type/guards" +
70
- " - #{self.name}" if same_name_diff_guards.exists?
71
-
72
61
  end
73
62
 
74
63
  validates_presence_of :name
@@ -105,13 +105,22 @@ class Marty::DataGrid < Marty::Base
105
105
  self
106
106
  end
107
107
 
108
+ def self.register_rule_handler(handler)
109
+ (@@rule_handlers ||= []) << handler
110
+ end
111
+ def update_rules(old, new)
112
+ @@rule_handlers.each { |rh| rh.call(old, new) }
113
+ end
114
+
108
115
  # FIXME: not sure what's the right way to perform the save in a
109
116
  # transaction -- i.e. together with build_index. before_save would
110
117
  # be OK, but then save inside it would cause an infinite loop.
111
118
  def save!
112
119
  if self.changed?
113
120
  transaction do
121
+ nc, nw, n = [name_changed?, name_was, name]
114
122
  res = super
123
+ update_rules(nw, n) if nc && nw.present?
115
124
  reload
116
125
  build_index
117
126
  res
@@ -5,15 +5,6 @@ class Marty::DeloreanRule < Marty::BaseRule
5
5
 
6
6
  def validate
7
7
  super
8
- if self.class.where(obsoleted_dt: 'infinity', name: name).
9
- where.not(id: id).
10
- where("(start_dt, coalesce(end_dt, 'infinity')) OVERLAPS (?, ?)",
11
- start_dt, end_dt || 'infinity').exists?
12
- return errors[:base] <<
13
- "Can't have rule with same name and overlapping start/end dates"\
14
- " - #{name}"
15
- end
16
-
17
8
  return errors[:base] = "Start date must be before end date" if
18
9
  start_dt && end_dt && start_dt >= end_dt
19
10
 
@@ -54,13 +45,13 @@ class Marty::DeloreanRule < Marty::BaseRule
54
45
  computed_guards.keys
55
46
  end
56
47
 
57
- def compres_keys
58
- defkeys = (Marty::Config[self.class.results_cfg_var] || {}).keys +
59
- ["adjustment", "breakeven"]
60
- results.keys.select{|k| defkeys.include?(k)} + grid_keys
48
+ def comp_res_keys(ecl)
49
+ defkeys = (Marty::Config[self.class.results_cfg_var] || {}).keys
50
+ results.keys.map {|k| k.ends_with?("_grid") ? ecl.grid_final_name(k) : k}.
51
+ select{|k| defkeys.include?(k)} + grid_keys(ecl)
61
52
  end
62
- def grid_keys
63
- grids.keys.map{|k|k.ends_with?("_grid") ? k : k + "_grid"}
53
+ def grid_keys(eclass)
54
+ grids.keys.map{|k| eclass.grid_final_name(k) }
64
55
  end
65
56
  def base_compute(params, dgparams=params)
66
57
  eclass = engine && engine.constantize || Marty::RuleScriptSet
@@ -79,11 +70,12 @@ class Marty::DeloreanRule < Marty::BaseRule
79
70
  end
80
71
  grids_computed = false
81
72
  grid_results = {}
73
+ crkeys = comp_res_keys(eclass)
82
74
  if (results.keys - fixed_results.keys).present?
83
75
  begin
84
76
  eval_result = engine.evaluate(
85
77
  eclass.node_name,
86
- compres_keys,
78
+ crkeys,
87
79
  params + {
88
80
  "dgparams__" => dgparams,
89
81
  })
@@ -91,7 +83,7 @@ class Marty::DeloreanRule < Marty::BaseRule
91
83
  rescue => e
92
84
  raise e, "Error (results) in rule '#{id}:#{name}': #{e}", e.backtrace
93
85
  end
94
- result = Hash[compres_keys.zip(eval_result)]
86
+ result = Hash[crkeys.zip(eval_result)]
95
87
  elsif fixed_results.keys.sort == results.keys.sort
96
88
  result = fixed_results
97
89
  end
@@ -99,7 +91,7 @@ class Marty::DeloreanRule < Marty::BaseRule
99
91
  pt = params['pt']
100
92
  gres = {}
101
93
  grid_results = grids.each_with_object({}) do |(gvar, gname), h|
102
- usename = gvar.ends_with?("_grid") ? gvar : gvar + "_grid"
94
+ usename = eclass.grid_final_name(gvar)
103
95
  next h[usename] = gres[gname] if gres[gname]
104
96
  dg = Marty::DataGrid.lookup(pt,gname)
105
97
  dgr = dg && dg.lookup_grid_distinct_entry(pt, dgparams)
@@ -118,4 +110,19 @@ class Marty::DeloreanRule < Marty::BaseRule
118
110
  q
119
111
  end
120
112
 
113
+ def self.get_grid_rename_handler(klass)
114
+ Proc.new do |old, new|
115
+ klass.where(obsoleted_dt: 'infinity').each do |r|
116
+ r.grids.each { |k, v| r.grids[k] = new if v == old }
117
+ r.results.each { |k, v| r.results[k] = %Q("#{new}") if
118
+ k.ends_with?("_grid") && r.fixed_results[k] == old }
119
+ r.save! if r.changed?
120
+ end
121
+ end
122
+ end
123
+
124
+ def self.init_dg_handler
125
+ Marty::DataGrid.register_rule_handler(get_grid_rename_handler(self))
126
+ end
127
+
121
128
  end
@@ -39,12 +39,19 @@ class Marty::RuleScriptSet < Delorean::AbstractContainer
39
39
  map {|k| %Q("#{k}": #{k}) }.join(",\n") + "}"
40
40
  end
41
41
 
42
+ def self.grid_final_name(dgid)
43
+ dgid.ends_with?("_grid") ? dgid + "_result" : dgid + "_grid_result"
44
+ end
42
45
  def expand_grid_code(h, dgid, dgname, cache, extra_params)
43
- final_name = dgid.ends_with?("_grid") ? dgid : dgid + "_grid"
46
+ final_name = self.class.grid_final_name(dgid)
44
47
  if cache[dgname]
45
48
  h[final_name] = "#{cache[dgname]}"
46
49
  else
47
- h["#{dgid}_dg__"] = "Marty::DataGrid.lookup(pt,'#{dgname}')"
50
+ h[dgid] = dgname
51
+ h["#{dgid}_dg__"] = <<~EOS
52
+ Marty::DataGrid.lookup(pt,#{dgid}) ||
53
+ ERR("grid '#{dgid}' ('%s') not found" % #{dgid})
54
+ EOS
48
55
  h["#{dgid}_dgp__"] = "dgparams__ + \n" + self.class.indent(paramify_h(h))
49
56
  lgde = "lookup_grid_distinct_entry"
50
57
  h["#{dgid}_h__"] = "#{dgid}_dg__.#{lgde}(pt,#{dgid}_dgp__)"
@@ -69,7 +76,7 @@ class Marty::RuleScriptSet < Delorean::AbstractContainer
69
76
  dgcache = {}
70
77
  h = {}
71
78
  rule.grids.each do |k, v|
72
- expand_grid_code(h, k, v, dgcache, {})
79
+ expand_grid_code(h, k.ends_with?('_grid')?k:k+'_grid', %Q("#{v}"), dgcache, {})
73
80
  end
74
81
  h.map { |k, v| write_attr(k, v) }.join("\n") + "\n"
75
82
  end
@@ -106,6 +113,7 @@ class Marty::RuleScriptSet < Delorean::AbstractContainer
106
113
  #puts '-'
107
114
  #puts code
108
115
  #puts '-'*10
116
+
109
117
  code
110
118
  end
111
119
 
data/lib/marty/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
@@ -10,7 +10,7 @@ class Gemini::MyRule < Marty::DeloreanRule
10
10
  find_by_group_id group_id
11
11
  end
12
12
 
13
- mcfly_validates_uniqueness_of :name, scope: [:start_dt, :end_dt]
13
+ mcfly_validates_uniqueness_of :name
14
14
 
15
15
  def self.guard_info
16
16
  super + {"g_array" => { multi: true, type: :string,
@@ -43,4 +43,5 @@ class Gemini::MyRule < Marty::DeloreanRule
43
43
  base_compute(*args)
44
44
  end
45
45
 
46
+ self.init_dg_handler
46
47
  end
@@ -10,7 +10,7 @@ class Gemini::XyzRule < Marty::DeloreanRule
10
10
  find_by_group_id group_id
11
11
  end
12
12
 
13
- mcfly_validates_uniqueness_of :name, scope: [:start_dt, :end_dt]
13
+ mcfly_validates_uniqueness_of :name
14
14
 
15
15
  def self.results_cfg_var
16
16
  'RULEOPTS_XYZ'
@@ -59,5 +59,5 @@ class Gemini::XyzRule < Marty::DeloreanRule
59
59
  res.all?
60
60
  end
61
61
 
62
-
62
+ self.init_dg_handler
63
63
  end
@@ -83,6 +83,7 @@ feature 'rule view', js: true do
83
83
  wait_for_ajax
84
84
  fill_in('name', with: 'abc')
85
85
  press('OK')
86
+ wait_for_ajax
86
87
  expect(page).to have_content("Rule type can't be blank")
87
88
  expect(page).to have_content("Start dt can't be blank")
88
89
  # create and verify rule
@@ -126,6 +127,7 @@ feature 'rule view', js: true do
126
127
  press("Edit")
127
128
  fill_in(:g_string, with: "12345")
128
129
  press("OK")
130
+ wait_for_ajax
129
131
  expect(page).to have_content("Bad value '12345' for 'g_string'")
130
132
  # type validation (range)
131
133
  fill_in(:g_string, with: "Hi Mom")
@@ -136,6 +138,7 @@ feature 'rule view', js: true do
136
138
  fill_in(:g_integer, with: 123)
137
139
  fill_in(:g_range, with: "asfd")
138
140
  press("OK")
141
+ wait_for_ajax
139
142
  expect(page).to have_content("Wrong type for 'g_range'")
140
143
  # validate rule
141
144
  fill_in(:g_range, with: "<=100")
@@ -170,15 +173,18 @@ feature 'rule view', js: true do
170
173
  press("Edit")
171
174
  fill_in(:computed_guards, with: 'sadf asdf ljsf')
172
175
  press("OK")
176
+ wait_for_ajax
173
177
  exp = "Computed - Error in rule 'abc' field 'computed_guards': Syntax error on line 1"
174
178
  expect(page).to have_content(exp)
175
179
  fill_in(:computed_guards, with: 'sadf = 123j s /*fdjOIb')
176
180
  press("OK")
181
+ wait_for_ajax
177
182
  exp = "Computed - Error in rule 'abc' field 'computed_guards': syntax error"
178
183
  expect(page).to have_content(exp)
179
184
  fill_in(:computed_guards, with: '')
180
185
  fill_in(:results, with: %Q(abc = "def"\ndef = 5\nxyz=def+10\nsadf asdf lsf))
181
186
  press("OK")
187
+ wait_for_ajax
182
188
  exp = "Computed - Error in rule 'abc' field 'results': Syntax error on line 4"
183
189
  expect(page).to have_content(exp)
184
190
  fill_in(:results,
@@ -186,21 +192,18 @@ feature 'rule view', js: true do
186
192
  exp = "Computed - Error in rule 'abc' field 'results': Keyword 'abc' specified more"\
187
193
  " than once (line 4)"
188
194
  press("OK")
195
+ wait_for_ajax
189
196
  expect(page).to have_content(exp)
190
197
  fill_in(:results,
191
198
  with: %Q(abc = "def"\ndef = "abc"\nklm = "3"))
192
199
  press("OK")
200
+ wait_for_ajax
193
201
 
194
202
  press("Dup in form")
195
- press("OK")
196
- exp = Regexp.new("Can't have rule with same name and overlapping start"\
197
- "/end dates - abc")
198
- expect(page).to have_content(exp)
199
203
  netzke_find('Single Guard', 'combobox').select_values("G2V3")
200
204
  press("OK")
201
- exp = Regexp.new("Can't have rule with same name and different "\
202
- "type/guards - abc")
203
- expect(page).to have_content(exp)
205
+ wait_for_ajax
206
+ expect(page).to have_content(/record must be unique/)
204
207
 
205
208
  press("Cancel")
206
209
  # column sorting, etc
@@ -261,5 +264,43 @@ feature 'rule view', js: true do
261
264
  %Q({"grid1":"DataGrid2"}),
262
265
  %Q({"grid1":"DataGrid1"}),
263
266
  %Q({"grid1":"DataGrid1"})])
267
+ press("Applications")
268
+ press("Data Grids")
269
+ dgv = netzke_find("data_grid_view")
270
+ cvs = dgv.col_values(:name, 4, 0)
271
+ ind1 = cvs.index("DataGrid1")+1
272
+ ind4 = cvs.index("DataGrid4")+1
273
+ dgv.select_row(ind1)
274
+ press("Edit")
275
+ fill_in("Name", with: "DataGrid1 new")
276
+ press("OK")
277
+ wait_for_ajax
278
+ dgv.select_row(ind4)
279
+ press("Edit")
280
+ fill_in("Name", with: "DataGrid4 new")
281
+ press("OK")
282
+ wait_for_ajax
283
+
284
+ go_to_xyz_rules
285
+ wait_for_ajax
286
+
287
+ names = xrv.col_values(:name, 5, 0)
288
+ gvs = xrv.col_values(:grids, 5, 0)
289
+ g1h = {"grid1"=>"DataGrid1 new"}
290
+ expect(JSON.parse(gvs[names.index("ZRule1")])).to eq(g1h)
291
+ expect(JSON.parse(gvs[names.index("ZRule2")])).to eq(g1h)
292
+
293
+ go_to_my_rules
294
+ wait_for_ajax
295
+
296
+ names = mrv.col_values(:name, 8, 0)
297
+ gvs = mrv.col_values(:grids, 8, 0)
298
+ rvs = mrv.col_values(:results, 8, 0)
299
+ expect(JSON.parse(gvs[names.index('abc')])).to eq(g1h)
300
+ expect(JSON.parse(gvs[names.index('Rule2b')])).to eq(g1h +
301
+ {"grid2"=>"DataGrid2"})
302
+ expect(JSON.parse(rvs[names.index('Rule5')])["other_grid"]).to eq(
303
+ '"DataGrid4 new"')
304
+
264
305
  end
265
306
  end
@@ -9,6 +9,6 @@ Rule2,SimpleRule,2017-2-1 14:00:00,2017-4-1,true,"{""g_array"":[""G1V2""],""g_si
9
9
  ""stringwithhash"": ""\"" string that contains a # character\""""}"
10
10
  Rule2a,SimpleRule,2017-2-1 14:00:00,2017-4-1,true,"{""g_array"":[""G1V2""],""g_single"":""G2V3"",""g_string"":""abc"",""g_bool"":true,""g_range"":""(,50]"",""g_integer"":99}",,,"{""simple_result"":""\""b value\"""", ""sr2"":""true"", ""sr3"": ""123""}"
11
11
  Rule2b,SimpleRule,2017-2-1 14:00:00,2017-4-1,true,"{""g_array"":[""G1V2""],""g_single"":""G2V3"",""g_string"":""abc"",""g_bool"":true,""g_range"":""(,50]"",""g_integer"":999}",,"{""grid1"":""DataGrid1"",""grid2"":""DataGrid2""}",
12
- Rule3,ComplexRule,2017-3-1 00:00:00,2017-4-1,false,"{""g_array"":[""G1V2"",""G1V3""],""g_string"":""def"",""g_integer"":11}","{""cguard1"":""1==1"",""cguard2"":""param2 == 'abc'""}","{""grid1"":""DataGrid1"",""grid2"":""DataGrid2""}","{""simple_result"":""\""c value\"""",""computed_value"":""if paramb then param1 / (grid1_grid||1) else (grid2_grid||1) / param1""}"
13
- Rule4,ComplexRule,2017-4-1 15:00:01,2017-5-1,,"{""g_array"":[""G1V2"",""G1V3""],""g_string"":""Hi Mom"",""g_integer"":11}","{""cguard1"":""1==1"",""cguard2"":""param2 == \""abc\""""}","{""grid1"":""DataGrid1"",""grid2"":""DataGrid2""}","{""simple_result"":""\""c value\"""",""grid_sum"":""(grid1_grid||0)+(grid2_grid||0)""}"
14
- Rule5,ComplexRule,2017-4-2 15:00:01,2017-5-1,,"{""g_string"":""zzz"",""g_integer"":3757,""g_has_default"":""foo""}","{""cguard1"":""1==1""}",,"{""flavor"": ""[\""cherry\"",\""lemon\""][param2]"",""other_grid"": ""DataGrid4"",""final_value"": ""other_grid * 3""}"
12
+ Rule3,ComplexRule,2017-3-1 00:00:00,2017-4-1,false,"{""g_array"":[""G1V2"",""G1V3""],""g_string"":""def"",""g_integer"":11}","{""cguard1"":""1==1"",""cguard2"":""param2 == 'abc'""}","{""grid1"":""DataGrid1"",""grid2"":""DataGrid2""}","{""simple_result"":""\""c value\"""",""computed_value"":""if paramb then param1 / (grid1_grid_result||1) else (grid2_grid_result||1) / param1""}"
13
+ Rule4,ComplexRule,2017-4-1 15:00:01,2017-5-1,,"{""g_array"":[""G1V2"",""G1V3""],""g_string"":""Hi Mom"",""g_integer"":11}","{""cguard1"":""1==1"",""cguard2"":""param2 == \""abc\""""}","{""grid1"":""DataGrid1"",""grid2"":""DataGrid2""}","{""computed_name_grid"":""\""DataGrid\""+\""X\"""", ""simple_result"":""computed_name_grid"",""grid_sum"":""computed_name_grid_result + (grid1_grid_result||0)+(grid2_grid_result||0)""}"
14
+ Rule5,ComplexRule,2017-4-2 15:00:01,2017-5-1,,"{""g_string"":""zzz"",""g_integer"":3757,""g_has_default"":""foo""}","{""cguard1"":""1==1""}",,"{""flavor"": ""[\""cherry\"",\""lemon\""][param2]"",""other_grid"": ""\""DataGrid4\"""",""final_value"": ""other_grid_result * 3""}"
@@ -9,6 +9,7 @@ module Marty::RuleSpec
9
9
  Marty::Config['RULEOPTS_MYRULE']={'simple_result'=>{},
10
10
  'computed_value'=>{},
11
11
  'final_value'=>{},
12
+ 'grid_sum'=>{}
12
13
  }
13
14
  Marty::Config['RULEOPTS_XYZ']={'bvlength'=>{},
14
15
  'bv'=>{},
@@ -265,6 +266,10 @@ module Marty::RuleSpec
265
266
  Gemini::MyRule.get_matches('infinity',
266
267
  {'rule_type'=>'ComplexRule'},
267
268
  {"g_integer"=>3757}).first }
269
+ let(:gridcomputedname) {
270
+ Gemini::MyRule.get_matches('infinity',
271
+ {'rule_type'=>'ComplexRule'},
272
+ {"g_string"=>"Hi Mom", "g_integer"=>11}).first }
268
273
  it "computed guards work" do
269
274
  c = complex.compute({"pt"=>Time.zone.now,
270
275
  'param2'=>'def'})
@@ -291,8 +296,8 @@ module Marty::RuleSpec
291
296
  expect(simple2b.compute({"pt"=>Time.zone.now,
292
297
  'param1'=> 66,
293
298
  'param2'=>'abc',
294
- 'paramb'=>false})).to eq({"grid1_grid"=>3,
295
- "grid2_grid"=>1300})
299
+ 'paramb'=>false})).to eq({"grid1_grid_result"=>3,
300
+ "grid2_grid_result"=>1300})
296
301
 
297
302
  end
298
303
  it "returns computed results" do
@@ -301,7 +306,8 @@ module Marty::RuleSpec
301
306
  'param2'=>'abc',
302
307
  'paramb'=>false})
303
308
  expect(c).to eq({"simple_result"=>"c value",
304
- "computed_value"=>19, "grid1_grid"=>3, "grid2_grid"=>1300})
309
+ "computed_value"=>19, "grid1_grid_result"=>3,
310
+ "grid2_grid_result"=>1300})
305
311
  end
306
312
  it "returns computed results (with delorean import)" do
307
313
  c = xyz.compute({"pt"=>Time.zone.now+1,
@@ -309,7 +315,15 @@ module Marty::RuleSpec
309
315
  "p2"=>3,
310
316
  "flavor"=>"cherry"})
311
317
  expect(c).to eq({"bvlength"=>13,"bv"=>"cherry --> 36",
312
- "grid1_grid"=>19})
318
+ "grid1_grid_result"=>19})
319
+ end
320
+ it "reports bad grid name" do
321
+ exp = Regexp.new("Error .results. in rule '\\d+:Rule4': "\
322
+ "grid 'computed_name_grid' .'DataGridX'. not found")
323
+ expect{gridcomputedname.compute({"pt"=>Time.zone.now,
324
+ 'param1'=> 66,
325
+ 'param2'=>'abc',
326
+ 'paramb'=>false})}.to raise_error(exp)
313
327
  end
314
328
  it "grids embedded in result work properly and receive prior attrs" do
315
329
  v = altgridmethod.compute({"pt"=>Time.zone.now,
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.2.2
4
+ version: 1.2.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: 2018-02-01 00:00:00.000000000 Z
17
+ date: 2018-02-06 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: pg