marty 2.1.5 → 2.3.0
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 +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -4
- data/app/components/marty/auth_app.rb +3 -3
- data/app/components/marty/auth_app/client/auth_app.js +1 -3
- data/app/components/marty/base_rule_view.rb +32 -20
- data/app/components/marty/data_grid_view.rb +3 -3
- data/app/components/marty/event_view.rb +0 -5
- data/app/components/marty/form.rb +8 -1
- data/app/components/marty/form/client/form.css +3 -0
- data/app/components/marty/grid.rb +174 -33
- data/app/components/marty/import_view.rb +151 -0
- data/app/components/marty/main_auth_app.rb +28 -28
- data/app/components/marty/mcfly_grid_panel.rb +1 -1
- data/app/components/marty/new_posting_form.rb +3 -3
- data/app/components/marty/new_posting_window.rb +5 -6
- data/app/components/marty/posting_grid.rb +2 -2
- data/app/components/marty/posting_window.rb +1 -2
- data/app/components/marty/promise_view.rb +11 -6
- data/app/components/marty/record_form_window.rb +1 -1
- data/app/components/marty/report_form.rb +4 -4
- data/app/components/marty/report_select.rb +1 -1
- data/app/components/marty/script_form.rb +4 -4
- data/app/components/marty/script_grid.rb +2 -2
- data/app/components/marty/script_tester.rb +1 -1
- data/app/components/marty/simple_app.rb +1 -2
- data/app/components/marty/simple_app/client/statusbar_ext.js +1 -1
- data/app/components/marty/tag_grid.rb +1 -1
- data/app/components/marty/user_view.rb +5 -5
- data/app/controllers/marty/job_controller.rb +5 -1
- data/app/models/marty/base.rb +0 -15
- data/app/models/marty/data_grid.rb +1 -1
- data/app/models/marty/log.rb +1 -0
- data/app/models/marty/promise.rb +27 -84
- data/app/models/marty/vw_promise.rb +72 -0
- data/app/views/layouts/marty/application.html.erb +6 -3
- data/config/locales/en.yml +4 -0
- data/db/migrate/410_jsonb_promise_result.rb +9 -0
- data/db/migrate/411_create_vw_promises.rb +26 -0
- data/lib/marty/data_change.rb +3 -4
- data/lib/marty/data_conversion.rb +1 -2
- data/lib/marty/data_importer.rb +13 -14
- data/lib/marty/javascript/{overrides.js → grid_view_in_form.js} +10 -6
- data/lib/marty/mcfly_model.rb +13 -20
- data/lib/marty/monkey.rb +33 -40
- data/lib/marty/promise_job.rb +8 -2
- data/lib/marty/promise_proxy.rb +6 -11
- data/lib/marty/rule_script_set.rb +5 -2
- data/lib/marty/version.rb +1 -1
- data/marty.gemspec +1 -1
- data/other/marty/diagnostic/delayed_job_workers.rb +8 -5
- data/spec/controllers/job_controller_spec.rb +34 -15
- data/spec/dummy/app/components/gemini/my_rule_view.rb +6 -0
- data/spec/dummy/app/models/gemini/helper.rb +2 -2
- data/spec/dummy/config/application.rb +1 -1
- data/spec/features/rule_spec.rb +100 -5
- data/spec/fixtures/csv/rule/MyRule.csv +1 -1
- data/spec/job_helper.rb +2 -4
- data/spec/lib/data_importer_spec.rb +10 -10
- data/spec/lib/delorean_query_spec.rb +13 -2
- data/spec/lib/logger_spec.rb +16 -14
- data/spec/models/data_grid_spec.rb +4 -10
- data/spec/models/promise_spec.rb +8 -8
- data/spec/models/rule_spec.rb +7 -7
- data/spec/spec_helper.rb +1 -1
- metadata +10 -5
@@ -1,8 +1,11 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
|
-
<head>
|
4
|
-
|
5
|
-
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
5
|
+
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css"
|
6
|
+
integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ"
|
7
|
+
crossorigin="anonymous">
|
8
|
+
<title><%= Rails.application.class.parent %></title>
|
6
9
|
<%= load_netzke theme: Rails.configuration.marty.extjs_theme %>
|
7
10
|
<%= csrf_meta_tag %>
|
8
11
|
</head>
|
data/config/locales/en.yml
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
class CreateVwPromises < ActiveRecord::Migration[5.1]
|
2
|
+
def up
|
3
|
+
execute <<SQL
|
4
|
+
drop view if exists marty_vw_promises;
|
5
|
+
create or replace view marty_vw_promises
|
6
|
+
as
|
7
|
+
select
|
8
|
+
id,
|
9
|
+
title,
|
10
|
+
user_id,
|
11
|
+
cformat,
|
12
|
+
parent_id,
|
13
|
+
job_id,
|
14
|
+
status,
|
15
|
+
start_dt,
|
16
|
+
end_dt
|
17
|
+
from marty_promises;
|
18
|
+
|
19
|
+
grant select on marty_vw_promises to public;
|
20
|
+
|
21
|
+
SQL
|
22
|
+
end
|
23
|
+
def down
|
24
|
+
execute "drop view if exists marty_vw_promises;"
|
25
|
+
end
|
26
|
+
end
|
data/lib/marty/data_change.rb
CHANGED
@@ -141,9 +141,8 @@ class Marty::DataChange
|
|
141
141
|
' OR (created_dt >= ? AND created_dt < ?)'
|
142
142
|
|
143
143
|
# find all changes from t0 to t1 -- orders by id to get the lower
|
144
|
-
# ones since those are the original version in Mcfly.
|
145
|
-
|
146
|
-
changes = klass.unscoped.select("DISTINCT ON (group_id) *").
|
144
|
+
# ones since those are the original version in Mcfly.
|
145
|
+
changes = klass.select("DISTINCT ON (group_id) *").
|
147
146
|
where(change_q, t0, t1, t0, t1).
|
148
147
|
order("group_id, id").
|
149
148
|
to_a
|
@@ -174,7 +173,7 @@ class Marty::DataChange
|
|
174
173
|
change_q = '(obsoleted_dt >= ? AND obsoleted_dt < ?)' +
|
175
174
|
' OR (created_dt >= ? AND created_dt < ?)'
|
176
175
|
|
177
|
-
countq = klass.
|
176
|
+
countq = klass.where(change_q, t0, t1, t0, t1)
|
178
177
|
dataq = klass.where(change_q, t0, t1, t0, t1)
|
179
178
|
|
180
179
|
if ids
|
@@ -157,8 +157,7 @@ class Marty::DataConversion
|
|
157
157
|
|
158
158
|
raise "no keys for #{klass} -- #{options}" if find_options.empty?
|
159
159
|
|
160
|
-
|
161
|
-
q = klass.unscoped.where(find_options)
|
160
|
+
q = klass.where(find_options)
|
162
161
|
q = q.where("obsoleted_dt >= ? AND created_dt < ?", dt, dt) if
|
163
162
|
dt && Mcfly.has_mcfly?(klass)
|
164
163
|
|
data/lib/marty/data_importer.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
module Marty
|
2
|
-
class
|
3
|
-
|
2
|
+
class DataImporter
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :lines
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def initialize(message, lines)
|
7
|
+
msg = lines && lines.respond_to?(:join) ?
|
8
|
+
"#{message} - lines: #{lines.join(',')}" : message
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
super(msg)
|
11
|
+
@lines = lines
|
12
|
+
end
|
11
13
|
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class DataImporter
|
15
14
|
# perform cleaning and do_import and summarize its results
|
16
15
|
def self.do_import_summary(klass,
|
17
16
|
data,
|
@@ -81,14 +80,14 @@ module Marty
|
|
81
80
|
end
|
82
81
|
rescue => exc
|
83
82
|
# to find problems with the importer, comment out the rescue block
|
84
|
-
raise
|
83
|
+
raise Error.new(exc.to_s, [eline])
|
85
84
|
end
|
86
85
|
|
87
86
|
ids = {}
|
88
87
|
# raise an error if record referenced more than once.
|
89
88
|
res.each_with_index do
|
90
89
|
|(op, id), line|
|
91
|
-
raise
|
90
|
+
raise Error.
|
92
91
|
new("record referenced more than once", [ids[id], line]) if
|
93
92
|
op != :blank && ids.member?(id) && !allow_dups
|
94
93
|
|
@@ -100,12 +99,12 @@ module Marty
|
|
100
99
|
klass.send(validation_function.to_sym, ids.keys) if
|
101
100
|
validation_function
|
102
101
|
rescue => exc
|
103
|
-
raise
|
102
|
+
raise Error.new(exc.to_s, [])
|
104
103
|
end
|
105
104
|
|
106
105
|
remainder_ids = cleaner_ids - ids.keys
|
107
106
|
|
108
|
-
raise
|
107
|
+
raise Error.
|
109
108
|
new("Missing import data. " +
|
110
109
|
"Please provide header line and at least one data line.", [1]) if
|
111
110
|
ids.keys.compact.count == 0
|
@@ -12,16 +12,21 @@ Ext.define('Netzke.Grid.EventHandlers', {
|
|
12
12
|
}
|
13
13
|
},
|
14
14
|
|
15
|
-
|
15
|
+
netzkeReloadStore: function(opts={}) {
|
16
16
|
var store = this.getStore();
|
17
17
|
|
18
|
-
// MONKEY: add
|
19
|
-
store.fireEvent('
|
18
|
+
// MONKEY: add beforenetzkereload and netzkerevent on store
|
19
|
+
store.fireEvent('beforenetzkereload');
|
20
|
+
var callback = opts.callback;
|
21
|
+
opts.callback = function() {
|
22
|
+
if (callback) { callback() }
|
23
|
+
store.fireEvent('netzkereload');
|
24
|
+
}
|
20
25
|
|
21
26
|
// NETZKE'S HACK to work around buffered store's buggy reload()
|
22
27
|
if (!store.lastRequestStart) {
|
23
|
-
store.load();
|
24
|
-
} else store.reload();
|
28
|
+
store.load(opts);
|
29
|
+
} else store.reload(opts);
|
25
30
|
},
|
26
31
|
});
|
27
32
|
|
@@ -74,4 +79,3 @@ Ext.define('Netzke.Grid.Columns', {
|
|
74
79
|
};
|
75
80
|
},
|
76
81
|
});
|
77
|
-
|
data/lib/marty/mcfly_model.rb
CHANGED
@@ -52,6 +52,10 @@ module Mcfly::Model
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
def hash_if_necessary(q, private)
|
56
|
+
!private && q.is_a?(ActiveRecord::Base) ? make_openstruct(q) : q
|
57
|
+
end
|
58
|
+
|
55
59
|
def base_mcfly_lookup(meth, name, options = {}, &block)
|
56
60
|
|
57
61
|
priv = options[:private]
|
@@ -70,19 +74,7 @@ module Mcfly::Model
|
|
70
74
|
|
71
75
|
q = q.first if q.respond_to?(:first) && options[:mode] == :first
|
72
76
|
|
73
|
-
|
74
|
-
|
75
|
-
case
|
76
|
-
when q.is_a?(ActiveRecord::Relation)
|
77
|
-
# shouldn't happen - lookups that are mode nil should be
|
78
|
-
# private raise "#{self}.#{name} can't convert
|
79
|
-
# ActiveRecord::Relation to OpenStruct"
|
80
|
-
q
|
81
|
-
when q.is_a?(ActiveRecord::Base)
|
82
|
-
make_openstruct(q)
|
83
|
-
else
|
84
|
-
q
|
85
|
-
end
|
77
|
+
hash_if_necessary(q, priv)
|
86
78
|
end
|
87
79
|
end
|
88
80
|
|
@@ -169,10 +161,11 @@ module Mcfly::Model
|
|
169
161
|
raise "#{rel_attr} should be mapped in attrs" if attrs[rel_attr].nil?
|
170
162
|
|
171
163
|
cat_assoc_klass = cat_assoc_name.constantize
|
164
|
+
cat_attr_id = "#{cat_attr}_id"
|
172
165
|
|
173
166
|
# replace rel_attr with cat_attr in attrs
|
174
167
|
pc_attrs = attrs.each_with_object({}) {|(k, v), h|
|
175
|
-
h[k == rel_attr ?
|
168
|
+
h[k == rel_attr ? cat_attr_id : k] = v
|
176
169
|
}
|
177
170
|
|
178
171
|
pc_name = "pc_#{name}".to_sym
|
@@ -186,6 +179,7 @@ module Mcfly::Model
|
|
186
179
|
|
187
180
|
# cache if mode is not nil
|
188
181
|
fn = options.fetch(:mode, :first) ? :cached_delorean_fn : :delorean_fn
|
182
|
+
priv = options[:private]
|
189
183
|
|
190
184
|
send(fn, name, sig: attrs.length+1) do
|
191
185
|
|ts, *args|
|
@@ -196,13 +190,12 @@ module Mcfly::Model
|
|
196
190
|
|
197
191
|
args[lpi] = cat_assoc_klass.
|
198
192
|
mcfly_pt(ts).
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
pluck("#{cat_attr}_id").
|
203
|
-
first
|
193
|
+
select(cat_attr_id).
|
194
|
+
find_by(rel_attr => rel).
|
195
|
+
send(cat_attr_id)
|
204
196
|
|
205
|
-
self.send(pc_name, ts, *args)
|
197
|
+
q = self.send(pc_name, ts, *args)
|
198
|
+
hash_if_necessary(q, priv)
|
206
199
|
end
|
207
200
|
end
|
208
201
|
end
|
data/lib/marty/monkey.rb
CHANGED
@@ -106,23 +106,6 @@ end
|
|
106
106
|
require 'netzke/basepack/data_adapters/active_record_adapter'
|
107
107
|
module Netzke::Basepack::DataAdapters
|
108
108
|
class ActiveRecordAdapter < AbstractAdapter
|
109
|
-
# FIXME: another giant hack to handle lazy_load columns.
|
110
|
-
# Modified original count_records to call count on first passed column.name
|
111
|
-
# when lazy-loaded. Otherwise, we run into issues with
|
112
|
-
# counting records in the default_scope placed by the lazy_load
|
113
|
-
# module.
|
114
|
-
def count_records(params, columns=[])
|
115
|
-
|
116
|
-
relation = @relation || get_relation(params)
|
117
|
-
columns.each do |c|
|
118
|
-
assoc, method = c[:name].split('__')
|
119
|
-
relation = relation.includes(assoc.to_sym).references(assoc.to_sym) if method
|
120
|
-
end
|
121
|
-
|
122
|
-
@model.const_defined?(:SELECT_COLS) ? relation.count(columns.first.name) :
|
123
|
-
relation.count
|
124
|
-
end
|
125
|
-
|
126
109
|
######################################################################
|
127
110
|
# The following is a hack to get around Netzke's broken handling
|
128
111
|
# of filtering on PostgreSQL enums columns.
|
@@ -238,11 +221,32 @@ class ActiveRecord::Relation
|
|
238
221
|
tb = cls.table_name
|
239
222
|
self.where("#{tb}.obsoleted_dt >= ? AND #{tb}.created_dt < ?", pt, pt)
|
240
223
|
end
|
224
|
+
|
225
|
+
def attributes
|
226
|
+
to_a.map(&:attributes)
|
227
|
+
end
|
241
228
|
end
|
242
229
|
|
243
230
|
######################################################################
|
244
231
|
|
245
232
|
class ActiveRecord::Base
|
233
|
+
MCFLY_PT_SIG = [1, 1]
|
234
|
+
|
235
|
+
# FIXME: hacky signatures for AR queries on classes
|
236
|
+
COUNT_SIG = [0, 0]
|
237
|
+
DISTINCT_SIG = [0, 100]
|
238
|
+
FIND_BY_SIG = [0, 100]
|
239
|
+
FIRST_SIG = [0, 1]
|
240
|
+
GROUP_SIG = [1, 100]
|
241
|
+
JOINS_SIG = [1, 100]
|
242
|
+
LAST_SIG = [0, 1]
|
243
|
+
LIMIT_SIG = [1, 1]
|
244
|
+
NOT_SIG = [1, 100]
|
245
|
+
ORDER_SIG = [1, 100]
|
246
|
+
PLUCK_SIG = [1, 100]
|
247
|
+
SELECT_SIG = [1, 100]
|
248
|
+
WHERE_SIG = [0, 100]
|
249
|
+
|
246
250
|
class << self
|
247
251
|
alias_method :old_joins, :joins
|
248
252
|
|
@@ -258,22 +262,23 @@ class ActiveRecord::Base
|
|
258
262
|
end
|
259
263
|
end
|
260
264
|
|
261
|
-
|
262
|
-
|
265
|
+
ar_instances = [ActiveRecord::Relation, ActiveRecord::QueryMethods::WhereChain]
|
266
|
+
|
267
|
+
args_hack = [ar_instances] + [[Object, nil]]*10
|
263
268
|
|
264
269
|
Delorean::RUBY_WHITELIST.merge!(
|
265
|
-
count: [
|
270
|
+
count: [ar_instances],
|
266
271
|
distinct: args_hack,
|
267
272
|
find_by: args_hack,
|
268
273
|
group: args_hack,
|
269
274
|
joins: args_hack,
|
270
|
-
limit: [
|
275
|
+
limit: [ar_instances, Integer],
|
271
276
|
not: args_hack,
|
272
277
|
order: args_hack,
|
273
278
|
pluck: args_hack,
|
274
279
|
select: args_hack,
|
275
280
|
where: args_hack,
|
276
|
-
mcfly_pt: [
|
281
|
+
mcfly_pt: [ar_instances,
|
277
282
|
[Date, Time, ActiveSupport::TimeWithZone, String],
|
278
283
|
[nil, Class]],
|
279
284
|
lookup_grid_distinct_entry: [OpenStruct,
|
@@ -293,22 +298,10 @@ end
|
|
293
298
|
######################################################################
|
294
299
|
|
295
300
|
class OpenStruct
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
end
|
300
|
-
def save!
|
301
|
-
loc = %r([^/]+:[0-9]+).match(caller.first)[0]
|
302
|
-
raise "save! called from #{loc} on #{self}"
|
303
|
-
end
|
304
|
-
def reload
|
305
|
-
loc = %r([^/]+:[0-9]+).match(caller.first)[0]
|
306
|
-
raise "reload called from #{loc} on #{self}"
|
301
|
+
# the default as_json produces {"table"=>h} which is quite goofy
|
302
|
+
def as_json(*)
|
303
|
+
self.to_h
|
307
304
|
end
|
308
|
-
#def method_missing(meth, *args)
|
309
|
-
# puts caller[0..8]
|
310
|
-
# super
|
311
|
-
#end
|
312
305
|
end
|
313
306
|
|
314
307
|
######################################################################
|
@@ -322,10 +315,10 @@ module Netzke
|
|
322
315
|
|
323
316
|
include_core_js(res)
|
324
317
|
|
325
|
-
# MONKEY: load javascript
|
326
|
-
|
318
|
+
# MONKEY: load marty custom javascript
|
319
|
+
marty_javascripts = Dir["#{File.dirname(__FILE__)}/javascript/*.js"]
|
327
320
|
|
328
|
-
(Netzke::Core.ext_javascripts +
|
321
|
+
(Netzke::Core.ext_javascripts + marty_javascripts).each do |path|
|
329
322
|
f = File.new(path)
|
330
323
|
res << f.read
|
331
324
|
end
|
data/lib/marty/promise_job.rb
CHANGED
@@ -10,6 +10,10 @@ class Delorean::BaseModule::NodeCall
|
|
10
10
|
params[:_user_id] = _e[:_user_id] || Mcfly.whodunnit.try(:id)
|
11
11
|
end
|
12
12
|
|
13
|
+
# def log(msg)
|
14
|
+
# open('/tmp/dj.out', 'a') { |f| f.puts msg }
|
15
|
+
# end
|
16
|
+
|
13
17
|
# Monkey-patch '|' method for Delorean NodeCall to create promise
|
14
18
|
# jobs and return promise proxy objects.
|
15
19
|
def |(args)
|
@@ -25,11 +29,13 @@ class Delorean::BaseModule::NodeCall
|
|
25
29
|
nn = node.is_a?(Class) ? node.name : node.to_s
|
26
30
|
begin
|
27
31
|
# make sure params is serialzable before starting a Job
|
28
|
-
|
32
|
+
JSON.dump(params)
|
29
33
|
rescue => exc
|
30
|
-
raise "non-serializable parameters"
|
34
|
+
raise "non-serializable parameters: #{params} #{exc}"
|
31
35
|
end
|
32
36
|
|
37
|
+
# log "||||| #{args.inspect} #{params.inspect}"
|
38
|
+
|
33
39
|
title = params["p_title"] || "#{script}::#{nn.demodulize}"
|
34
40
|
timeout = params["p_timeout"] || Marty::Promise::DEFAULT_PROMISE_TIMEOUT
|
35
41
|
hook = params["p_hook"]
|
data/lib/marty/promise_proxy.rb
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
class Marty::PromiseProxy < BasicObject
|
5
5
|
NOT_SET = ::Object.new.freeze
|
6
6
|
METH_SET = ::Set[
|
7
|
-
:marshal_load,
|
8
|
-
:marshal_dump,
|
9
7
|
:force,
|
10
8
|
:__force__,
|
11
9
|
# Added for Rails 4 -- were causing forced eval.
|
@@ -13,25 +11,22 @@ class Marty::PromiseProxy < BasicObject
|
|
13
11
|
# ActiveRecord treats assignment to proxy objs.
|
14
12
|
:is_a?,
|
15
13
|
:nested_under_indifferent_access,
|
14
|
+
:as_json,
|
16
15
|
]
|
17
16
|
|
18
17
|
instance_methods.each {|m| undef_method m unless m =~ /^(__.*|object_id)$/}
|
19
18
|
|
20
19
|
def initialize(promise_id, timeout, attr=nil)
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def marshal_dump
|
25
|
-
[@promise.id, @timeout, @attr]
|
26
|
-
end
|
27
|
-
|
28
|
-
def marshal_load(args)
|
29
|
-
promise_id, @timeout, @attr = args
|
20
|
+
promise_id, @timeout, @attr = promise_id, timeout, attr
|
30
21
|
@promise = ::Marty::Promise.find(promise_id)
|
31
22
|
@mutex = ::Mutex.new
|
32
23
|
@result = NOT_SET
|
33
24
|
end
|
34
25
|
|
26
|
+
def as_json(*)
|
27
|
+
{'__promise__' => [@promise.id, @timeout, @attr]}
|
28
|
+
end
|
29
|
+
|
35
30
|
def __promise__
|
36
31
|
@promise
|
37
32
|
end
|