marty 2.0.1 → 2.0.2

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: 31ab53bcb7bcc26bfa4bd1d400c5e0c7861558d3
4
- data.tar.gz: c12dae6177787b1cd2eefb4416c11b15155a4395
3
+ metadata.gz: '08f9abbd9c473713331bb0ade7453ac85f1c4842'
4
+ data.tar.gz: d0251f02426640781822b048f6203f0597f73227
5
5
  SHA512:
6
- metadata.gz: 6c435cd40922422b864e5dc5ed4d20536ca8a50317b917a4b53b299a9d949ef67594ceb8707c38c822efd3024264e7a1832f3707ed8d2ae039957848681cf627
7
- data.tar.gz: 17a9348a816387d216a59739eac52b9cca47790ec8dd5cb469eaee93c660c83a29d40f8b9afac1ccc422d4ea6245386948732c5a87632fc612793b5a0677d4c0
6
+ metadata.gz: 2cab552bb2a885d177007686a476e57a28a72ab02af0ce904b0e81c0dde0dd63ed0ce773399000ea3283ee618023909259618e5e1e95e6547372ca31cefb2077
7
+ data.tar.gz: f39020a718bcb428a4c3171c6e21c0973b6b5bb3f8efb02bbc7237f4f386606e5c321cadaaea77ed375f39f2b07dfc239f8b55ad849d6be08591a2408c1626ac
@@ -54,17 +54,22 @@ module Mcfly::Model
54
54
 
55
55
  def base_mcfly_lookup(meth, name, options = {}, &block)
56
56
 
57
- sig = options[:sig]
57
+ priv = options[:private]
58
+ sig = priv ? -1 : options[:sig]
59
+
60
+ # add an extra argument to the sig to receive the openstruct conversion
61
+ # options hash (unless private)
58
62
  newsig = sig.is_a?(Array) ? [sig[0], sig[1]+1] :
59
63
  sig == -1 ? sig : [sig, sig+1]
60
64
  options[:sig] = newsig
61
- asig = options[:asig] || newsig[1]-1
62
65
 
63
66
  send(meth, name, options) do |ts, *pargs|
64
67
  raise "time cannot be nil" if ts.nil?
65
68
 
66
- args, opts = pargs.last.is_a?(Hash) && pargs.length == asig ?
67
- [pargs[0..-2], pargs.last] :
69
+ # get the options hash if method is not private and last arg is a hash
70
+ # and pargs len = max sig (-1 because ts is separated in the arg list)
71
+ args, opts = !priv && pargs.last.is_a?(Hash) &&
72
+ pargs.length == newsig[1]-1 ? [pargs[0..-2], pargs.last] :
68
73
  [pargs, {}]
69
74
 
70
75
  ts = Mcfly.normalize_infinity(ts)
@@ -73,18 +78,19 @@ module Mcfly::Model
73
78
  "#{table_name}.created_dt < ?", ts, ts).scoping do
74
79
  block.call(ts, *args)
75
80
  end
81
+ next q if priv
82
+
76
83
  fa = get_final_attrs(opts)
77
84
  opts += {"fa"=>fa}
78
-
79
- q = q.select(*fa) if fa.present? &&
80
- q.respond_to?(:select) && !q.is_a?(Array) &&
81
- !q.is_a?(Hash)
85
+ q = q.select(*fa) if fa.present? && q.is_a?(ActiveRecord::Relation)
82
86
 
83
87
  case
84
88
  when opts["no_convert"] == true
85
89
  q
86
90
  when q.is_a?(ActiveRecord::Relation)
87
- q.map{|ar| make_openstruct(ar, opts)}
91
+ # shouldn't happen - lookups that are mode nil should be private
92
+ # raise "#{self}.#{name} can't convert ActiveRecord::Relation to OpenStruct"
93
+ q
88
94
  when q.is_a?(ActiveRecord::Base)
89
95
  make_openstruct(q, opts)
90
96
  else
@@ -133,11 +139,8 @@ module Mcfly::Model
133
139
  raise "bad attrs" unless Array === attrs
134
140
  end
135
141
 
136
- actual_sig = attrs.length + 1
137
142
  fn = cache ? :cached_delorean_fn : :delorean_fn
138
- sig = options[:private] ? -1 : actual_sig
139
-
140
- base_mcfly_lookup(fn, name, {sig: sig, asig: actual_sig}) do
143
+ base_mcfly_lookup(fn, name, options + {sig: attrs.length+1}) do
141
144
  |t, *attr_list|
142
145
 
143
146
  attr_list_ids = attr_list.each_with_index.map {|x, i|
data/lib/marty/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Marty
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
@@ -25,5 +25,72 @@ module Gemini
25
25
  rec
26
26
  }
27
27
  end
28
+
29
+ gen_mcfly_lookup :lookup, {
30
+ entity: true,
31
+ note_rate: false
32
+ }
33
+ gen_mcfly_lookup :lookup_p, {
34
+ entity: true,
35
+ note_rate: false
36
+ }, private: true
37
+ gen_mcfly_lookup :clookup, {
38
+ entity: true,
39
+ note_rate: false
40
+ }, cache: true
41
+ gen_mcfly_lookup :clookup_p, {
42
+ entity: true,
43
+ note_rate: false
44
+ }, cache: true, private: true
45
+ gen_mcfly_lookup :lookupn, {
46
+ entity: true,
47
+ note_rate: false
48
+ }, mode: nil
49
+ gen_mcfly_lookup :lookupn_p, {
50
+ entity: true,
51
+ note_rate: false
52
+ }, private: true, mode: nil
53
+ gen_mcfly_lookup :clookupn, {
54
+ entity: true,
55
+ note_rate: false
56
+ }, cache: true, mode: nil
57
+ gen_mcfly_lookup :clookupn_p, {
58
+ entity: true,
59
+ note_rate: false
60
+ }, cache: true, private: true, mode: nil
61
+
62
+ mcfly_lookup :a_func, sig: 3 do
63
+ |pt, e_id, bc_id|
64
+ where(entity_id: e_id, bud_category_id: bc_id).
65
+ order(:settlement_mm)
66
+ end
67
+
68
+ mcfly_lookup :b_func, sig: [3, 4] do
69
+ |pt, e_id, bc_id, mm = nil|
70
+ q = where(entity_id: e_id, bud_category_id: bc_id)
71
+ q = q.where(settlement_mm: mm) if mm
72
+ q.order(:settlement_mm).first
73
+ end
74
+
75
+ mcfly_lookup :a_func_p, sig: 3, private: true do
76
+ |pt, e_id, bc_id|
77
+ where(entity_id: e_id, bud_category_id: bc_id).
78
+ order(:settlement_mm)
79
+ end
80
+
81
+ mcfly_lookup :b_func_p, sig: [3, 4], private: true do
82
+ |pt, e_id, bc_id, mm = nil|
83
+ q = where(entity_id: e_id, bud_category_id: bc_id)
84
+ q = q.where(settlement_mm: mm) if mm
85
+ q.order(:settlement_mm)
86
+ end
87
+
88
+ cached_mcfly_lookup :ca_func, sig: 3 do
89
+ |pt, e_id, bc_id|
90
+ where(entity_id: e_id, bud_category_id: bc_id).
91
+ order(:settlement_mm)
92
+ end
93
+
94
+
28
95
  end
29
96
  end
@@ -74,6 +74,10 @@ A:
74
74
  EOF
75
75
 
76
76
  describe 'DeloreanQuery' do
77
+ before(:all) do
78
+ @clean_file = "/tmp/clean_#{Process.pid}.psql"
79
+ save_clean_db(@clean_file)
80
+ end
77
81
  before(:each) do
78
82
  marty_whodunnit
79
83
  Marty::DataImporter.do_import_summary(Gemini::BudCategory, bud_cats)
@@ -86,7 +90,10 @@ EOF
86
90
 
87
91
  @engine = Marty::ScriptSet.new.get_engine("A")
88
92
  end
89
-
93
+ after(:all) do
94
+ restore_clean_db(@clean_file)
95
+ Marty::ScriptSet.clear_cache
96
+ end
90
97
  it "perfroms join+count" do
91
98
  res = @engine.evaluate("A", "c", {})
92
99
 
@@ -0,0 +1,255 @@
1
+ require "spec_helper"
2
+
3
+ module Marty
4
+
5
+ entities =<<EOF
6
+ name
7
+ PLS
8
+ EOF
9
+ bud_cats =<<EOF
10
+ name
11
+ Conv Fixed 30
12
+ Conv Fixed 20
13
+ EOF
14
+
15
+ fannie_bup =<<EOF
16
+ entity bud_category note_rate buy_up buy_down settlement_mm settlement_yy
17
+ Conv Fixed 30 2.250 4.42000 7.24000 12 2012
18
+ Conv Fixed 30 2.375 4.42000 7.24000 12 2012
19
+ Conv Fixed 30 2.500 4.41300 7.22800 12 2012
20
+ Conv Fixed 30 2.625 4.37500 7.16200 12 2012
21
+ Conv Fixed 30 2.750 4.32900 7.09300 12 2012
22
+ Conv Fixed 20 2.875 4.24800 6.95900 12 2012
23
+ Conv Fixed 20 2.875 4.24800 6.95900 11 2012
24
+ PLS Conv Fixed 30 2.250 5.42000 8.24000 12 2012
25
+ PLS Conv Fixed 30 2.375 5.42000 8.24000 12 2012
26
+ PLS Conv Fixed 30 2.500 5.41300 8.22800 12 2012
27
+ PLS Conv Fixed 30 2.625 5.37500 8.16200 12 2012
28
+ PLS Conv Fixed 30 2.750 5.32900 8.09300 12 2012
29
+ PLS Conv Fixed 20 2.875 5.24800 7.95900 12 2012
30
+ PLS Conv Fixed 20 2.875 5.24800 7.95900 11 2012
31
+ EOF
32
+
33
+ script =<<EOF
34
+ A:
35
+ pt =?
36
+ entity =?
37
+ note_rate =?
38
+
39
+ extra = {"include_attrs": ["settlement_mm", "settlement_yy"],
40
+ "link_attrs": {"entity": "name",
41
+ "bud_category": "name"}}
42
+ ex2 = {"include_attrs": ["settlement_mm", "settlement_yy", "entity_id",
43
+ "bud_category_id"]}
44
+
45
+ lookup = Gemini::FannieBup.lookup( pt, entity, note_rate)
46
+ lookup_extra = Gemini::FannieBup.lookup( pt, entity, note_rate, extra)
47
+
48
+ clookup = Gemini::FannieBup.clookup( pt, entity, note_rate)
49
+
50
+ lookupn = Gemini::FannieBup.lookupn( pt, entity, note_rate)
51
+ lookupn_extra = Gemini::FannieBup.lookupn( pt, entity, note_rate, ex2)
52
+
53
+ clookupn = Gemini::FannieBup.clookupn(pt, entity, note_rate)
54
+
55
+ a_func = Gemini::FannieBup.a_func('infinity', 1, 2)
56
+ a_func_extra = Gemini::FannieBup.a_func('infinity', 1, 2, ex2)
57
+ b_func = Gemini::FannieBup.b_func('infinity',1, 2, 12)
58
+ b_func_extra = Gemini::FannieBup.b_func('infinity',1, 2, 12, extra)
59
+ ca_func = Gemini::FannieBup.ca_func('infinity',1, 2, ex2)
60
+
61
+ EOF
62
+ errscript =<<EOF
63
+ Err:
64
+ pt =?
65
+ entity =?
66
+ note_rate =?
67
+ result = Gemini::FannieBup.%s(pt, entity, note_rate)
68
+ EOF
69
+ errscript2 =<<EOF
70
+ Err:
71
+ pt =?
72
+ e_id =?
73
+ bc_id =?
74
+ result = Gemini::FannieBup.%s(pt, e_id, bc_id)
75
+ EOF
76
+ errscript3 =<<EOF
77
+ Err:
78
+ pt =?
79
+ e_id =?
80
+ bc_id =?
81
+ mm =?
82
+ result = Gemini::FannieBup.%s(pt, e_id, bc_id, mm)
83
+ EOF
84
+
85
+ describe 'McflyModel' do
86
+ before(:all) do
87
+ @clean_file = "/tmp/clean_#{Process.pid}.psql"
88
+ save_clean_db(@clean_file)
89
+ marty_whodunnit
90
+ dt = Date.today
91
+ Marty::DataImporter.do_import_summary(Gemini::Entity, entities)
92
+ Marty::DataImporter.do_import_summary(Gemini::BudCategory, bud_cats)
93
+ Marty::DataImporter.do_import_summary(Gemini::FannieBup, fannie_bup)
94
+ Marty::Script.load_script_bodies(
95
+ {
96
+ "AA" => script,
97
+ }, dt)
98
+ @errs = ['E1', 'lookup_p',
99
+ 'E2', 'clookup_p',
100
+ 'E3', 'lookupn_p',
101
+ 'E4', 'clookupn_p']
102
+
103
+ @errs.in_groups_of(2) do |name, fn|
104
+ Marty::Script.load_script_bodies(
105
+ {
106
+ name => (errscript % fn),
107
+ }, Date.today)
108
+ end
109
+
110
+ Marty::Script.load_script_bodies({'E5'=>(errscript2 % 'a_func_p')}, dt)
111
+ Marty::Script.load_script_bodies({'E6'=>(errscript3 % 'b_func_p')}, dt)
112
+
113
+ @engine = Marty::ScriptSet.new.get_engine("AA")
114
+ end
115
+ after(:all) do
116
+ restore_clean_db(@clean_file)
117
+ Marty::ScriptSet.clear_cache
118
+ end
119
+ let(:params) {{"pt" =>'infinity',
120
+ "entity" => Gemini::Entity.all.first,
121
+ "note_rate" => 2.875}}
122
+ it "lookup mode default" do
123
+ a1 = @engine.evaluate("A", "lookup", params)
124
+ a2 = @engine.evaluate("A", "clookup", params)
125
+ expect(a1).to eq(a2) # cache/non return same
126
+ expect(a1.class).to eq(OpenStruct) # mode default so return OS
127
+ expect(a2.class).to eq(OpenStruct)
128
+
129
+ # check that keys are non mcfly non uniqueness
130
+ expect(a1.to_h.keys.to_set).to eq(Set[:buy_up, :buy_down])
131
+ end
132
+
133
+ it "lookup non generated" do
134
+ # a1-a3 will be AR Relations
135
+ # b1-b2 will be OpenStructs because the b fns return #first
136
+ a1 = @engine.evaluate("A", "a_func", {})
137
+ a2 = @engine.evaluate("A", "ca_func", {})
138
+ a3 = @engine.evaluate("A", "a_func_extra", {})
139
+ b1 = @engine.evaluate("A", "b_func", {})
140
+ b2 = @engine.evaluate("A", "b_func_extra", {})
141
+
142
+ # all return relations
143
+ expect(ActiveRecord::Relation === a1).to be_truthy
144
+ expect(ActiveRecord::Relation === a2).to be_truthy
145
+ expect(ActiveRecord::Relation === a3).to be_truthy
146
+ expect(ActiveRecord::Base === a1.first).to be_truthy
147
+ expect(ActiveRecord::Base === a2.first).to be_truthy
148
+ expect(ActiveRecord::Base === a3.first).to be_truthy
149
+
150
+ expect(a1.to_a.count).to eq(2)
151
+ expect(a2.to_a.count).to eq(2)
152
+ expect(a3.to_a.count).to eq(2)
153
+
154
+ # a1 lookup did not include extra attrs
155
+ expect(a1.first.attributes.keys.to_set).to eq(Set["id", "buy_up", "buy_down"])
156
+
157
+ # a2 and a3 did
158
+ s = Set["id", "entity_id", "bud_category_id", "buy_up", "buy_down",
159
+ "settlement_mm", "settlement_yy"]
160
+ expect(a2.first.attributes.keys.to_set).to eq(s)
161
+ expect(a3.first.attributes.keys.to_set).to eq(s)
162
+
163
+ # a1 is AR but still missing the FK entity_id so will raise
164
+ expect{a1.first.entity}.to raise_error(/missing attribute: entity_id/)
165
+
166
+ # a3 included those so can access them
167
+ expect(a3.first.entity.name).to eq('PLS')
168
+ expect(a3.first.bud_category.name).to eq('Conv Fixed 20')
169
+
170
+ expect(b1.class).to eq(OpenStruct)
171
+ expect(b2.class).to eq(OpenStruct)
172
+
173
+ # make sure b1-b2 have correct keys and extra stuff
174
+ expect(b1.to_h.keys.to_set).to eq(Set[:buy_up, :buy_down])
175
+ expect(b2.to_h.keys.to_set).to eq(
176
+ Set[:buy_up, :buy_down, :settlement_mm, :settlement_yy,
177
+ :entity, :bud_category])
178
+ expect(b2.entity.name).to eq('PLS')
179
+ expect(b2.bud_category.name).to eq('Conv Fixed 20')
180
+ end
181
+ it "lookup extra values" do
182
+ a2 = @engine.evaluate("A", "lookup_extra", params)
183
+ expect(a2.class).to eq(OpenStruct)
184
+
185
+ # check that extra values are there
186
+ expect(a2.to_h.keys.to_set).to eq(Set[:buy_up, :buy_down, :settlement_mm,
187
+ :settlement_yy, :entity,
188
+ :bud_category])
189
+ # check that linked values are there
190
+ expect(a2.entity.name).to eq("PLS")
191
+ expect(a2.bud_category.name).to eq("Conv Fixed 20")
192
+ end
193
+ it "lookup mode nil extra values" do
194
+ all = @engine.evaluate("A", "lookupn_extra", params)
195
+
196
+ # mode nil always returns AR
197
+ expect(ActiveRecord::Relation === all).to be_truthy
198
+
199
+ # check keys returned
200
+ all.each do |a2|
201
+ expect(a2.attributes.keys.to_set).to eq(
202
+ Set["id", "buy_up", "buy_down", "settlement_mm",
203
+ "settlement_yy", "entity_id", "bud_category_id"])
204
+ if a2.entity_id
205
+ expect(a2.entity.name).to eq("PLS")
206
+ expect(ActiveRecord::Base === a2.entity).to be_truthy
207
+ expect(a2.bud_category.name).to eq("Conv Fixed 20")
208
+ expect(ActiveRecord::Base === a2.bud_category).to be_truthy
209
+ end
210
+ end
211
+ end
212
+ it "lookup mode nil" do
213
+ # make sure ARs are returned
214
+ a1 = @engine.evaluate("A", "lookupn", params)
215
+ a2 = @engine.evaluate("A", "clookupn", params)
216
+ expect(a1).to eq(a2)
217
+ expect(ActiveRecord::Relation === a1).to be_truthy
218
+ expect(a1.to_a.count).to eq(4)
219
+ end
220
+ it "private methods can't be called by delorean" do
221
+ # generated methods
222
+ aggregate_failures "errors" do
223
+ @errs.in_groups_of(2) do |name, fn|
224
+ err = /Too many args to #{fn}/
225
+ expect{Marty::ScriptSet.new.get_engine(name)}.to raise_error(
226
+ Delorean::BadCallError, err)
227
+ end
228
+ end
229
+
230
+ # non-generated
231
+ aggregate_failures "errors" do
232
+ ['E5', 'a_func_p', 'E6', 'b_func_p'].in_groups_of(2) do |scr, fn|
233
+ err = /Too many args to #{fn}/
234
+ expect{Marty::ScriptSet.new.get_engine(scr)}.to raise_error(
235
+ Delorean::BadCallError, err)
236
+ end
237
+ end
238
+ end
239
+ it "caching times" do
240
+ ts = DateTime.now
241
+ x=Benchmark.measure { 10000.times {
242
+ Gemini::FannieBup.a_func(ts,
243
+ 1, 2)
244
+ }
245
+ }
246
+ y=Benchmark.measure { 10000.times {
247
+ Gemini::FannieBup.ca_func(ts,
248
+ 1, 2)
249
+ }
250
+ }
251
+ # x time should be 30x or more than y time
252
+ expect(x.real / y.real).to be > 30
253
+ end
254
+ end
255
+ end
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: 2.0.1
4
+ version: 2.0.2
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-04-09 00:00:00.000000000 Z
17
+ date: 2018-04-11 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: pg
@@ -1631,6 +1631,7 @@ files:
1631
1631
  - spec/lib/delorean_query_spec.rb
1632
1632
  - spec/lib/json_schema_spec.rb
1633
1633
  - spec/lib/logger_spec.rb
1634
+ - spec/lib/mcfly_model_spec.rb
1634
1635
  - spec/lib/migrations/vw_marty_postings.sql.expected
1635
1636
  - spec/lib/migrations_spec.rb
1636
1637
  - spec/lib/xl_spec.rb