marty 1.2.2 → 1.2.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: 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