engine2 1.0.4 → 1.0.5
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 +0 -0
- data/Rakefile +1 -1
- data/app/{engine2actions.coffee → actions.coffee} +192 -142
- data/app/app.coffee +0 -0
- data/app/app.css +4 -0
- data/app/engine2.coffee +87 -175
- data/app/modal.coffee +133 -0
- data/bower.json +2 -1
- data/conf/message.yaml +0 -0
- data/conf/message_pl.yaml +0 -0
- data/config.coffee +11 -2
- data/engine2.gemspec +2 -2
- data/lib/engine2.rb +12 -10
- data/lib/engine2/action.rb +1290 -134
- data/lib/engine2/{meta/array_meta.rb → action/array.rb} +4 -3
- data/lib/engine2/{meta/decode_meta.rb → action/decode.rb} +16 -15
- data/lib/engine2/action/delete.rb +65 -0
- data/lib/engine2/action/form.rb +16 -0
- data/lib/engine2/{meta/infra_meta.rb → action/infra.rb} +118 -85
- data/lib/engine2/action/link.rb +117 -0
- data/lib/engine2/{meta/list_meta.rb → action/list.rb} +61 -62
- data/lib/engine2/action/save.rb +30 -0
- data/lib/engine2/action/view.rb +8 -0
- data/lib/engine2/action_node.rb +221 -0
- data/lib/engine2/core.rb +120 -77
- data/lib/engine2/handler.rb +9 -10
- data/lib/engine2/model.rb +4 -20
- data/lib/engine2/models/Files.rb +2 -1
- data/lib/engine2/models/UserInfo.rb +6 -3
- data/lib/engine2/post_bootstrap.rb +3 -2
- data/lib/engine2/pre_bootstrap.rb +1 -0
- data/lib/engine2/scheme.rb +98 -47
- data/lib/engine2/templates.rb +1 -0
- data/lib/engine2/type_info.rb +6 -4
- data/lib/engine2/version.rb +2 -1
- data/package.json +12 -10
- data/public/favicon.ico +0 -0
- data/public/img/ajax-loader-dark.gif +0 -0
- data/public/img/ajax-loader.gif +0 -0
- data/views/fields/blob.slim +0 -0
- data/views/fields/bs_select.slim +0 -0
- data/views/fields/bsselect_picker.slim +0 -0
- data/views/fields/bsselect_picker_opt.slim +0 -0
- data/views/fields/checkbox.slim +0 -0
- data/views/fields/checkbox_buttons.slim +0 -0
- data/views/fields/checkbox_buttons_opt.slim +0 -0
- data/views/fields/currency.slim +0 -0
- data/views/fields/date.slim +0 -0
- data/views/fields/date_range.slim +0 -0
- data/views/fields/date_time.slim +0 -0
- data/views/fields/datetime.slim +0 -0
- data/views/fields/decimal.slim +0 -0
- data/views/fields/decimal_date.slim +0 -0
- data/views/fields/decimal_time.slim +0 -0
- data/views/fields/email.slim +0 -0
- data/views/fields/file_store.slim +7 -7
- data/views/fields/input_text.slim +0 -0
- data/views/fields/integer.slim +0 -0
- data/views/fields/list_bsselect.slim +0 -0
- data/views/fields/list_bsselect_opt.slim +0 -0
- data/views/fields/list_buttons.slim +0 -0
- data/views/fields/list_buttons_opt.slim +0 -0
- data/views/fields/list_select.slim +0 -0
- data/views/fields/list_select_opt.slim +0 -0
- data/views/fields/password.slim +0 -0
- data/views/fields/radio_checkbox.slim +0 -0
- data/views/fields/scaffold.slim +0 -0
- data/views/fields/scaffold_picker.slim +0 -0
- data/views/fields/select_picker.slim +0 -0
- data/views/fields/select_picker_opt.slim +0 -0
- data/views/fields/text_area.slim +1 -0
- data/views/fields/time.slim +0 -0
- data/views/fields/typeahead_picker.slim +0 -0
- data/views/index.slim +3 -3
- data/views/infra/index.slim +0 -0
- data/views/infra/inspect.slim +20 -0
- data/views/modals/close_m.slim +0 -0
- data/views/modals/confirm_m.slim +0 -0
- data/views/modals/empty_m.slim +0 -0
- data/views/modals/menu_m.slim +1 -1
- data/views/modals/yes_no_m.slim +0 -0
- data/views/panels/menu_m.slim +1 -1
- data/views/scaffold/confirm.slim +0 -0
- data/views/scaffold/fields.slim +0 -0
- data/views/scaffold/form.slim +0 -0
- data/views/scaffold/form_collapse.slim +0 -0
- data/views/scaffold/form_tabs.slim +0 -0
- data/views/scaffold/list.slim +0 -0
- data/views/scaffold/message.slim +0 -0
- data/views/scaffold/search.slim +0 -0
- data/views/scaffold/search_collapse.slim +0 -0
- data/views/scaffold/search_tabs.slim +0 -0
- data/views/scaffold/view.slim +0 -0
- data/views/scaffold/view_collapse.slim +0 -0
- data/views/scaffold/view_tabs.slim +0 -0
- data/views/search_fields/bsmselect_picker.slim +0 -0
- data/views/search_fields/bsselect_picker.slim +0 -0
- data/views/search_fields/checkbox.slim +0 -0
- data/views/search_fields/checkbox2.slim +0 -0
- data/views/search_fields/checkbox_buttons.slim +0 -0
- data/views/search_fields/date_range.slim +0 -0
- data/views/search_fields/decimal_date_range.slim +0 -0
- data/views/search_fields/input_text.slim +0 -0
- data/views/search_fields/integer.slim +0 -0
- data/views/search_fields/integer_range.slim +0 -0
- data/views/search_fields/list_bsmselect.slim +0 -0
- data/views/search_fields/list_bsselect.slim +0 -0
- data/views/search_fields/list_buttons.slim +0 -0
- data/views/search_fields/list_select.slim +0 -0
- data/views/search_fields/scaffold_picker.slim +0 -0
- data/views/search_fields/select_picker.slim +0 -0
- data/views/search_fields/typeahead_picker.slim +0 -0
- metadata +41 -42
- data/lib/engine2/meta.rb +0 -1216
- data/lib/engine2/meta/delete_meta.rb +0 -60
- data/lib/engine2/meta/form_meta.rb +0 -15
- data/lib/engine2/meta/link_meta.rb +0 -134
- data/lib/engine2/meta/save_meta.rb +0 -50
- data/lib/engine2/meta/view_meta.rb +0 -7
- data/public/__sinatra__/404.png +0 -0
- data/public/__sinatra__/500.png +0 -0
data/lib/engine2/core.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#coding: utf-8
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module PrettyJSON
|
|
4
5
|
def to_json_pretty
|
|
@@ -13,9 +14,19 @@ class BigDecimal
|
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
|
|
17
|
+
class Sequel::SQL::QualifiedIdentifier
|
|
18
|
+
def to_json(*)
|
|
19
|
+
"\"#{table}__#{column}\""
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_sym
|
|
23
|
+
:"#{table}__#{column}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
16
27
|
class Object
|
|
17
28
|
def instance_variables_hash
|
|
18
|
-
instance_variables.
|
|
29
|
+
instance_variables.reduce({}) do |h, i|
|
|
19
30
|
h[i] = instance_variable_get(i)
|
|
20
31
|
h
|
|
21
32
|
end
|
|
@@ -25,16 +36,24 @@ end
|
|
|
25
36
|
class Proc
|
|
26
37
|
def to_json(*)
|
|
27
38
|
loc = source_location
|
|
28
|
-
"\"#<Proc:#{loc.first[/\w+.rb/]}:#{loc.last}>\""
|
|
39
|
+
loc ? "\"#<Proc:#{loc.first[/\w+.rb/]}:#{loc.last}>\"" : '"source unknown"'
|
|
29
40
|
end
|
|
30
41
|
|
|
31
42
|
def chain &blk
|
|
32
|
-
|
|
43
|
+
prc = self
|
|
33
44
|
lambda do |obj|
|
|
34
|
-
obj.instance_eval(&
|
|
45
|
+
obj.instance_eval(&prc)
|
|
35
46
|
obj.instance_eval(&blk)
|
|
36
47
|
end
|
|
37
48
|
end
|
|
49
|
+
|
|
50
|
+
def chain_args &blk
|
|
51
|
+
prc = self
|
|
52
|
+
lambda do |*args|
|
|
53
|
+
instance_exec(*args, &prc)
|
|
54
|
+
instance_exec(*args, &blk)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
38
57
|
end
|
|
39
58
|
|
|
40
59
|
class Hash
|
|
@@ -111,11 +130,27 @@ end
|
|
|
111
130
|
|
|
112
131
|
class Symbol
|
|
113
132
|
def icon
|
|
114
|
-
|
|
133
|
+
s = self
|
|
134
|
+
if s[0, 3] == 'fa_'
|
|
135
|
+
"<i class='fa fa-#{s[3 .. -1]}'></i>"
|
|
136
|
+
else
|
|
137
|
+
"<span class='glyphicon glyphicon-#{s}'></span>"
|
|
138
|
+
end
|
|
115
139
|
end
|
|
116
140
|
|
|
117
|
-
def
|
|
118
|
-
|
|
141
|
+
def q col
|
|
142
|
+
col.qualify self
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
module Faye
|
|
147
|
+
class WebSocket
|
|
148
|
+
module API
|
|
149
|
+
def send! msg
|
|
150
|
+
msg = msg.to_json if msg.is_a? Hash
|
|
151
|
+
send msg
|
|
152
|
+
end
|
|
153
|
+
end
|
|
119
154
|
end
|
|
120
155
|
end
|
|
121
156
|
|
|
@@ -125,13 +160,17 @@ class << Sequel
|
|
|
125
160
|
def split_keys id
|
|
126
161
|
id.split(Engine2::SETTINGS[:key_separator])
|
|
127
162
|
end
|
|
163
|
+
|
|
164
|
+
def join_keys keys
|
|
165
|
+
keys.join(Engine2::SETTINGS[:key_separator])
|
|
166
|
+
end
|
|
128
167
|
end
|
|
129
168
|
|
|
130
169
|
class Sequel::Database
|
|
131
170
|
attr_accessor :models, :default_schema
|
|
132
171
|
|
|
133
172
|
def cache_file
|
|
134
|
-
"#{Engine2::
|
|
173
|
+
"#{Engine2::SETTINGS.path_for(:db_path)}/#{opts[:orig_opts][:name]}.dump"
|
|
135
174
|
end
|
|
136
175
|
|
|
137
176
|
def load_schema_cache_from_file
|
|
@@ -144,7 +183,6 @@ class Sequel::Database
|
|
|
144
183
|
end
|
|
145
184
|
end
|
|
146
185
|
|
|
147
|
-
Sequel.quote_identifiers = false
|
|
148
186
|
Sequel.extension :core_extensions
|
|
149
187
|
Sequel::Inflections.clear
|
|
150
188
|
Sequel.alias_columns_in_joins = true
|
|
@@ -277,7 +315,7 @@ module E2Model
|
|
|
277
315
|
|
|
278
316
|
def primary_keys_qualified
|
|
279
317
|
# cache it ?
|
|
280
|
-
primary_keys.map{|k|
|
|
318
|
+
primary_keys.map{|k|table_name.q(k)}
|
|
281
319
|
end
|
|
282
320
|
|
|
283
321
|
def primary_keys_hash id
|
|
@@ -290,9 +328,8 @@ module E2Model
|
|
|
290
328
|
end
|
|
291
329
|
|
|
292
330
|
module DatasetMethods
|
|
293
|
-
|
|
294
331
|
def ensure_primary_key
|
|
295
|
-
pk =
|
|
332
|
+
pk = model.primary_keys
|
|
296
333
|
raise Engine2::E2Error.new("No primary key defined for model #{model}") unless pk && pk.all?
|
|
297
334
|
|
|
298
335
|
if opts_select = @opts[:select]
|
|
@@ -300,7 +337,7 @@ module E2Model
|
|
|
300
337
|
opts_select.each do |sel|
|
|
301
338
|
name = case sel
|
|
302
339
|
when Symbol
|
|
303
|
-
sel
|
|
340
|
+
sel
|
|
304
341
|
when Sequel::SQL::QualifiedIdentifier
|
|
305
342
|
sel.column
|
|
306
343
|
when Sequel::SQL::AliasedExpression
|
|
@@ -314,94 +351,85 @@ module E2Model
|
|
|
314
351
|
if pk.length == sel_pk.length
|
|
315
352
|
self
|
|
316
353
|
else
|
|
317
|
-
sels = (pk - sel_pk).map{|k|
|
|
354
|
+
sels = (pk - sel_pk).map{|k| model.table_name.q(k)}
|
|
318
355
|
select_more(*sels)
|
|
319
356
|
end
|
|
320
357
|
else
|
|
321
|
-
select(*pk.map{|k|
|
|
358
|
+
select(*pk.map{|k| model.table_name.q(k)})
|
|
322
359
|
end
|
|
323
360
|
|
|
324
361
|
end
|
|
325
362
|
|
|
363
|
+
def extract_select sel, al = nil, &blk
|
|
364
|
+
case sel
|
|
365
|
+
when Symbol
|
|
366
|
+
yield nil, sel, nil
|
|
367
|
+
when Sequel::SQL::QualifiedIdentifier
|
|
368
|
+
yield sel.table, sel.column, al
|
|
369
|
+
when Sequel::SQL::AliasedExpression, Sequel::SQL::Function
|
|
370
|
+
sel
|
|
371
|
+
# extract_select sel.expression, sel.aliaz, &blk
|
|
372
|
+
# expr = sel.expression
|
|
373
|
+
# yield expr.table, expr.column
|
|
374
|
+
else
|
|
375
|
+
raise Engine2::E2Error.new("Unknown selection #{sel}")
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
326
379
|
def setup! fields
|
|
327
380
|
joins = {}
|
|
328
381
|
type_info = model.type_info
|
|
329
382
|
model_table_name = model.table_name
|
|
330
383
|
|
|
331
|
-
@opts[:select].map
|
|
384
|
+
@opts[:select] = @opts[:select].map do |sel|
|
|
332
385
|
extract_select sel do |table, name, aliaz|
|
|
333
|
-
if table
|
|
386
|
+
info = if table
|
|
334
387
|
if table == model_table_name
|
|
335
|
-
|
|
388
|
+
model
|
|
336
389
|
else
|
|
337
|
-
|
|
338
|
-
raise Engine2::E2Error.new("Association #{table} not found for model #{model}") unless
|
|
339
|
-
|
|
340
|
-
end
|
|
341
|
-
# raise Engine2::E2Error.new("Model not found for table #{table} in model #{model}") unless m
|
|
342
|
-
info = m.type_info
|
|
390
|
+
assoc = model.many_to_one_associations[table] || model.many_to_many_associations[table]
|
|
391
|
+
raise Engine2::E2Error.new("Association #{table} not found for model #{model}") unless assoc
|
|
392
|
+
assoc.associated_class
|
|
393
|
+
end.type_info
|
|
343
394
|
else
|
|
344
|
-
|
|
395
|
+
type_info
|
|
345
396
|
end
|
|
346
397
|
|
|
347
|
-
f_info = info[name]
|
|
348
|
-
raise Engine2::E2Error.new("Column #{name} not found for table #{table || model_table_name}") unless f_info
|
|
349
|
-
|
|
350
398
|
table ||= model_table_name
|
|
351
|
-
|
|
352
399
|
if table == model_table_name
|
|
353
400
|
fields << name
|
|
354
401
|
else
|
|
355
|
-
fields <<
|
|
356
|
-
joins[table]
|
|
402
|
+
fields << table.q(name)
|
|
403
|
+
joins[table] ||= model.many_to_one_associations[table] || model.many_to_many_associations[table]
|
|
357
404
|
end
|
|
358
405
|
|
|
406
|
+
f_info = info[name]
|
|
407
|
+
raise Engine2::E2Error.new("Column #{name} not found for table #{table || model_table_name}") unless f_info
|
|
359
408
|
if f_info[:dummy]
|
|
360
409
|
nil
|
|
361
|
-
# elsif f_info[:type] == :blob_store
|
|
362
|
-
# # (~{name => nil}).as :name
|
|
363
|
-
# # Sequel.char_length(name).as name
|
|
364
|
-
# nil
|
|
365
410
|
else
|
|
411
|
+
qname = table.q(name)
|
|
366
412
|
if table != model_table_name
|
|
367
|
-
|
|
368
|
-
name.qualify(table).as(:"#{table}__#{name}")
|
|
369
|
-
else
|
|
370
|
-
name.qualify(table)
|
|
371
|
-
end
|
|
413
|
+
Sequel.alias_columns_in_joins ? qname.as(:"#{table}__#{name}") : qname
|
|
372
414
|
else
|
|
373
|
-
|
|
415
|
+
qname
|
|
374
416
|
end
|
|
375
417
|
end
|
|
376
418
|
end
|
|
377
419
|
end
|
|
378
420
|
|
|
379
|
-
@opts[:select].compact
|
|
421
|
+
@opts[:select].compact!.freeze
|
|
380
422
|
|
|
381
423
|
joins.reduce(self) do |joined, (table, assoc)|
|
|
382
424
|
m = assoc.associated_class
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
when Symbol
|
|
391
|
-
if sel.to_s =~ /^(\w+)__(\w+?)(?:___(\w+))?$/
|
|
392
|
-
yield $1.to_sym, $2.to_sym, $3 ? $3.to_sym : nil
|
|
393
|
-
else
|
|
394
|
-
yield nil, sel, al
|
|
425
|
+
case assoc[:type]
|
|
426
|
+
when :many_to_one
|
|
427
|
+
keys = assoc[:qualified_key]
|
|
428
|
+
joined.left_join(table, m.primary_keys.zip(keys.is_a?(Array) ? keys : [keys]))
|
|
429
|
+
when :many_to_many
|
|
430
|
+
joined.left_join(assoc[:join_table], assoc[:left_keys].zip(model.primary_keys)).left_join(m.table_name, m.primary_keys.zip(assoc[:right_keys]))
|
|
431
|
+
else unsupported_association
|
|
395
432
|
end
|
|
396
|
-
when Sequel::SQL::QualifiedIdentifier
|
|
397
|
-
yield sel.table, sel.column, al
|
|
398
|
-
when Sequel::SQL::AliasedExpression, Sequel::SQL::Function
|
|
399
|
-
sel
|
|
400
|
-
# extract_select sel.expression, sel.aliaz, &blk
|
|
401
|
-
# expr = sel.expression
|
|
402
|
-
# yield expr.table, expr.column
|
|
403
|
-
else
|
|
404
|
-
raise Engine2::E2Error.new("Unknown selection #{sel}")
|
|
405
433
|
end
|
|
406
434
|
end
|
|
407
435
|
|
|
@@ -433,10 +461,21 @@ end
|
|
|
433
461
|
module Engine2
|
|
434
462
|
LOCS ||= Hash.new{|h, k| ":#{k}:"}
|
|
435
463
|
PATH ||= File.expand_path('../..', File.dirname(__FILE__))
|
|
436
|
-
SETTINGS ||= {
|
|
464
|
+
SETTINGS ||= {
|
|
465
|
+
key_separator: '|',
|
|
466
|
+
app_path: 'app',
|
|
467
|
+
db_path: 'db',
|
|
468
|
+
model_path: 'models',
|
|
469
|
+
view_path: 'views',
|
|
470
|
+
asset_path: 'assets',
|
|
471
|
+
conf_path: 'conf'
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
def SETTINGS.path_for path
|
|
475
|
+
"#{self[:app_path]}/#{self[path]}"
|
|
476
|
+
end unless SETTINGS.frozen?
|
|
437
477
|
|
|
438
478
|
class << self
|
|
439
|
-
attr_reader :app
|
|
440
479
|
attr_reader :core_loaded
|
|
441
480
|
|
|
442
481
|
def database name
|
|
@@ -457,8 +496,9 @@ module Engine2
|
|
|
457
496
|
end
|
|
458
497
|
|
|
459
498
|
def bootstrap_e2db
|
|
460
|
-
|
|
461
|
-
|
|
499
|
+
e2_db_path = "#{Engine2::SETTINGS.path_for(:db_path)}/engine2.db"
|
|
500
|
+
e2_db_url = (defined? JRUBY_VERSION) ? "jdbc:sqlite:#{e2_db_path}" : "sqlite://#{e2_db_path}"
|
|
501
|
+
const_set :E2DB, connect(e2_db_url, loggers: [Logger.new($stdout)], convert_types: false, name: :engine2)
|
|
462
502
|
const_set :DUMMYDB, Sequel::Database.new(uri: 'dummy')
|
|
463
503
|
def DUMMYDB.synchronize *args;end
|
|
464
504
|
end
|
|
@@ -466,35 +506,38 @@ module Engine2
|
|
|
466
506
|
def reload
|
|
467
507
|
@core_loaded = true
|
|
468
508
|
t = Time.now
|
|
469
|
-
|
|
509
|
+
ActionNode.count = 0
|
|
470
510
|
SCHEMES.user.clear
|
|
471
511
|
|
|
472
512
|
Sequel::DATABASES.each do |db|
|
|
473
513
|
db.models.each{|n, m| Object.send(:remove_const, n) if Object.const_defined?(n)} unless db == E2DB || db == DUMMYDB
|
|
474
514
|
end
|
|
475
515
|
|
|
476
|
-
load "#{
|
|
516
|
+
load "#{Engine2::SETTINGS[:app_path]}/boot.rb"
|
|
477
517
|
|
|
478
518
|
Sequel::DATABASES.each &:load_schema_cache_from_file
|
|
479
519
|
@model_boot_blk.() if @model_boot_blk
|
|
480
520
|
load 'engine2/models/Files.rb'
|
|
481
521
|
load 'engine2/models/UserInfo.rb'
|
|
482
|
-
Dir["#{
|
|
522
|
+
Dir["#{Engine2::SETTINGS.path_for(:model_path)}/*"].each{|m| load m}
|
|
483
523
|
puts "MODELS: #{Sequel::DATABASES.reduce(0){|s, d|s + d.models.size}}, Time: #{Time.now - t}"
|
|
484
524
|
Sequel::DATABASES.each &:dump_schema_cache_to_file
|
|
485
525
|
|
|
486
526
|
send(:remove_const, :ROOT) if defined? ROOT
|
|
487
|
-
const_set(:ROOT,
|
|
527
|
+
const_set(:ROOT, ActionNode.new(nil, :api, RootAction, {}))
|
|
488
528
|
|
|
489
529
|
@boot_blk.(ROOT)
|
|
490
|
-
ROOT.
|
|
491
|
-
puts "BOOTSTRAP #{
|
|
530
|
+
ROOT.setup_node_tree
|
|
531
|
+
puts "BOOTSTRAP #{Engine2::SETTINGS[:name]}, Time: #{Time.new - t}"
|
|
492
532
|
end
|
|
493
533
|
|
|
494
|
-
def bootstrap
|
|
495
|
-
@app = app
|
|
534
|
+
def bootstrap path, settings = {}
|
|
496
535
|
SETTINGS.merge! settings
|
|
497
|
-
SETTINGS[:
|
|
536
|
+
SETTINGS[:path] = path
|
|
537
|
+
SETTINGS[:name] ||= File::basename(path)
|
|
538
|
+
SETTINGS.freeze
|
|
539
|
+
Handler.set :public_folder, "public"
|
|
540
|
+
Handler.set :views, [SETTINGS.path_for(:view_path), "#{Engine2::PATH}/views"]
|
|
498
541
|
bootstrap_e2db
|
|
499
542
|
|
|
500
543
|
require 'engine2/pre_bootstrap'
|
data/lib/engine2/handler.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Engine2
|
|
4
5
|
class Handler < Sinatra::Base
|
|
@@ -66,20 +67,20 @@ module Engine2
|
|
|
66
67
|
def serve_api_resource verb, path
|
|
67
68
|
path = path.split('/') # -1 ?
|
|
68
69
|
is_meta = path.pop if path.last == 'meta'
|
|
69
|
-
|
|
70
|
+
node = ROOT
|
|
70
71
|
path.each do |pat|
|
|
71
|
-
|
|
72
|
-
halt_not_found unless
|
|
73
|
-
halt_unauthorized unless
|
|
72
|
+
node = node[pat.to_sym]
|
|
73
|
+
halt_not_found unless node
|
|
74
|
+
halt_unauthorized unless node.check_access!(self)
|
|
74
75
|
end
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
action = node.*
|
|
77
78
|
response = if is_meta
|
|
78
|
-
params[:access] ?
|
|
79
|
+
params[:access] ? node.access_info(self) : {meta: action.meta, actions: node.nodes_info(self)}
|
|
79
80
|
else
|
|
80
|
-
if
|
|
81
|
+
if action.http_method == verb && action.invokable
|
|
81
82
|
begin
|
|
82
|
-
|
|
83
|
+
action.invoke!(self)
|
|
83
84
|
rescue => error
|
|
84
85
|
attachment nil, nil
|
|
85
86
|
# content_type :json
|
|
@@ -119,8 +120,6 @@ module Engine2
|
|
|
119
120
|
end
|
|
120
121
|
|
|
121
122
|
set :slim, pretty: true, sort_attrs: false
|
|
122
|
-
set :views, ["views", "#{PATH}/views"]
|
|
123
|
-
set :public_folder, "#{PATH}/public"
|
|
124
123
|
set :sessions, expire_after: 3600 # , :httponly => true, :secure => production?
|
|
125
124
|
|
|
126
125
|
helpers do
|
data/lib/engine2/model.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Engine2
|
|
4
5
|
module Model
|
|
@@ -74,6 +75,8 @@ module Engine2
|
|
|
74
75
|
decimal_field name, size, scale
|
|
75
76
|
when :blob
|
|
76
77
|
blob_field name, 100000
|
|
78
|
+
when :boolean
|
|
79
|
+
boolean_field name
|
|
77
80
|
when nil
|
|
78
81
|
# ignore nil type
|
|
79
82
|
else
|
|
@@ -284,7 +287,7 @@ module Engine2
|
|
|
284
287
|
with_errors = with.map{|w|record.errors[w]}
|
|
285
288
|
if with_errors.compact.empty?
|
|
286
289
|
all_fields = [field] + with
|
|
287
|
-
query = record.model.dataset
|
|
290
|
+
query = all_fields.reduce(record.model.dataset){|ds, f|ds.where f => record[f]}
|
|
288
291
|
query = query.exclude(record.model.primary_keys_hash(record.primary_key_values)) unless record.new?
|
|
289
292
|
unless query.empty?
|
|
290
293
|
msg = LOCS[:required_unique_value]
|
|
@@ -327,25 +330,6 @@ module Engine2
|
|
|
327
330
|
)
|
|
328
331
|
|
|
329
332
|
(AfterSaveProcessors ||= {}).merge!(
|
|
330
|
-
star_to_many_field: lambda{|record, field, info|
|
|
331
|
-
value = record.values[field]
|
|
332
|
-
if value && value.is_a?(Hash)
|
|
333
|
-
assoc = record.model.association_reflections[info[:assoc_name]]
|
|
334
|
-
other_model = assoc.associated_class
|
|
335
|
-
unlinked = value[:unlinked]
|
|
336
|
-
linked = value[:linked]
|
|
337
|
-
parent_key = record.primary_key_values
|
|
338
|
-
case assoc[:type]
|
|
339
|
-
when :one_to_many
|
|
340
|
-
StarToManyUnlinkMetaBase.one_to_many_unlink_db(other_model, assoc, unlinked) if unlinked
|
|
341
|
-
StarToManyLinkMeta.one_to_many_link_db(other_model, assoc, parent_key, linked) if linked
|
|
342
|
-
when :many_to_many
|
|
343
|
-
StarToManyUnlinkMetaBase.many_to_many_unlink_db(other_model, assoc, parent_key, unlinked) if unlinked
|
|
344
|
-
StarToManyLinkMeta.many_to_many_link_db(other_model, assoc, parent_key, linked) if linked
|
|
345
|
-
else unsupported_association
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
},
|
|
349
333
|
file_store: lambda{|m, v, info|
|
|
350
334
|
value = m.values[v]
|
|
351
335
|
files = E2Files.db[:files]
|
data/lib/engine2/models/Files.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module Engine2
|
|
4
5
|
E2DB.create_table :files do
|
|
@@ -28,7 +29,7 @@ module Engine2
|
|
|
28
29
|
search_live
|
|
29
30
|
|
|
30
31
|
on_change :model do |req, value|
|
|
31
|
-
#
|
|
32
|
+
# node.parent.*.assets[:model].select(:field).where(model: value).all.map{|rec|f = rec.values[:field]; [f, f]}
|
|
32
33
|
# render :field, list: {a: 1, b: 2}.to_a
|
|
33
34
|
end
|
|
34
35
|
|