ezframe 0.2.0 → 0.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/exe/check_column_yml +1 -1
- data/exe/dbmigrate +112 -90
- data/lib/ezframe.rb +6 -1
- data/lib/ezframe/auth.rb +31 -22
- data/lib/ezframe/column_set.rb +63 -37
- data/lib/ezframe/column_type.rb +85 -49
- data/lib/ezframe/config.rb +4 -4
- data/lib/ezframe/controller.rb +6 -6
- data/lib/ezframe/database.rb +20 -13
- data/lib/ezframe/editor.rb +5 -5
- data/lib/ezframe/editor_common.rb +56 -0
- data/lib/ezframe/{logger.rb → ezlog.rb} +7 -6
- data/lib/ezframe/ht.rb +1 -1
- data/lib/ezframe/html.rb +2 -2
- data/lib/ezframe/main_editor.rb +238 -0
- data/lib/ezframe/materialize.rb +4 -4
- data/lib/ezframe/message.rb +3 -3
- data/lib/ezframe/page_base.rb +9 -9
- data/lib/ezframe/route.rb +12 -9
- data/lib/ezframe/server.rb +10 -3
- data/lib/ezframe/single_page_editor.rb +205 -0
- data/lib/ezframe/sub_editor.rb +222 -0
- data/lib/ezframe/template.rb +1 -1
- data/lib/ezframe/util.rb +9 -5
- data/lib/ezframe/version.rb +1 -1
- metadata +8 -3
data/lib/ezframe/column_type.rb
CHANGED
@@ -31,8 +31,8 @@ module Ezframe
|
|
31
31
|
@attribute[:key].to_sym
|
32
32
|
end
|
33
33
|
|
34
|
-
def label
|
35
|
-
return nil if @attribute[:hidden]
|
34
|
+
def label(opts = {})
|
35
|
+
return nil if @attribute[:hidden] && !opts[:force]
|
36
36
|
@attribute[:label]
|
37
37
|
end
|
38
38
|
|
@@ -62,7 +62,11 @@ module Ezframe
|
|
62
62
|
|
63
63
|
def view(opts = {})
|
64
64
|
return nil if no_view?
|
65
|
-
@
|
65
|
+
if @attribute[:view_format]
|
66
|
+
return use_view_format(@attribute[:view_format], @value)
|
67
|
+
else
|
68
|
+
@value
|
69
|
+
end
|
66
70
|
end
|
67
71
|
|
68
72
|
def normalize(val)
|
@@ -92,12 +96,17 @@ module Ezframe
|
|
92
96
|
nil
|
93
97
|
end
|
94
98
|
|
95
|
-
#
|
96
|
-
def use_view_format(format_a,
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
# フォーマットに従って表示する
|
100
|
+
def use_view_format(format_a, val)
|
101
|
+
return nil unless val
|
102
|
+
if format_a.is_a?(String)
|
103
|
+
return format_a % val
|
104
|
+
else
|
105
|
+
fmt_a = format_a.clone
|
106
|
+
pattern = fmt_a.shift
|
107
|
+
value_a = fmt_a.map {|key| val.send(key) }
|
108
|
+
return pattern % value_a
|
109
|
+
end
|
101
110
|
end
|
102
111
|
end
|
103
112
|
|
@@ -117,7 +126,9 @@ module Ezframe
|
|
117
126
|
|
118
127
|
def form(opts = {})
|
119
128
|
return nil if no_edit? && !opts[:force]
|
120
|
-
|
129
|
+
key = self.key
|
130
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
131
|
+
h = Ht.input(type: "text", name: key, label: @attribute[:label], value: @value || "")
|
121
132
|
h[:class] = @attribute[:class] if @attribute[:class]
|
122
133
|
return h
|
123
134
|
end
|
@@ -136,7 +147,9 @@ module Ezframe
|
|
136
147
|
def form(opts = {})
|
137
148
|
return nil if no_edit? && !opts[:force]
|
138
149
|
val = @value
|
139
|
-
|
150
|
+
key = self.key
|
151
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
152
|
+
h = Ht.textarea(name: key, label: @attribute[:label], child: val)
|
140
153
|
h[:class] = @attribute[:class] if @attribute[:class]
|
141
154
|
return h
|
142
155
|
end
|
@@ -145,7 +158,17 @@ module Ezframe
|
|
145
158
|
class IntType < TextType
|
146
159
|
def view(opts = {})
|
147
160
|
return nil if no_view? && !opts[:force]
|
148
|
-
return @value
|
161
|
+
return nil unless @value
|
162
|
+
return nil if @attribute[:no_view_if_zero] && @value.to_i == 0
|
163
|
+
if @attribute[:view_format]
|
164
|
+
return use_view_format(@attribute[:view_format], @value)
|
165
|
+
else
|
166
|
+
if @attribute[:add_comma]
|
167
|
+
return @value.to_i.add_comma
|
168
|
+
else
|
169
|
+
return @value.to_s
|
170
|
+
end
|
171
|
+
end
|
149
172
|
end
|
150
173
|
|
151
174
|
def normalize(val)
|
@@ -170,13 +193,19 @@ module Ezframe
|
|
170
193
|
@value = nil
|
171
194
|
return
|
172
195
|
end
|
196
|
+
unless v.is_a?(Integer) || v.is_a?(String)
|
197
|
+
EzLog.debug("value must integer or string: key=#{self.key}, #{v}: class=#{v.class}")
|
198
|
+
return
|
199
|
+
end
|
173
200
|
v = normalize(v)
|
174
201
|
@value = v.to_i
|
175
202
|
end
|
176
203
|
|
177
204
|
def form(opts = {})
|
178
205
|
return nil if no_edit? && !opts[:force]
|
179
|
-
|
206
|
+
key = self.key
|
207
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
208
|
+
h = Ht.input(type: "number", name: key, label: @attribute[:label], value: @value || "")
|
180
209
|
h[:class] = @attribute[:class] if @attribute[:class]
|
181
210
|
return h
|
182
211
|
end
|
@@ -195,9 +224,7 @@ module Ezframe
|
|
195
224
|
end
|
196
225
|
|
197
226
|
class ForeignType < IntType
|
198
|
-
|
199
|
-
super
|
200
|
-
end
|
227
|
+
attr_accessor :db_data
|
201
228
|
|
202
229
|
def target_table
|
203
230
|
table = @attribute[:table]
|
@@ -224,20 +251,24 @@ module Ezframe
|
|
224
251
|
menu_a = data_h.map do |id, data|
|
225
252
|
[ data[:id], data[view_key&.to_sym] ]
|
226
253
|
end
|
227
|
-
|
254
|
+
key = self.key
|
255
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
256
|
+
return Ht.select(name: key, class: %w[browser-default], item: menu_a, value: @value)
|
228
257
|
end
|
229
258
|
|
230
259
|
def db_type
|
231
260
|
return "int"
|
232
261
|
end
|
233
|
-
end
|
234
262
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
263
|
+
def set_db_data
|
264
|
+
@db_data = {}
|
265
|
+
if @value
|
266
|
+
@db_data = DB::Cache[target_table.to_sym][@value]
|
267
|
+
end
|
239
268
|
end
|
269
|
+
end
|
240
270
|
|
271
|
+
class IdType < IntType
|
241
272
|
def form(opts = {})
|
242
273
|
return nil
|
243
274
|
end
|
@@ -247,11 +278,6 @@ module Ezframe
|
|
247
278
|
def initialize(attr = nil)
|
248
279
|
super(attr)
|
249
280
|
@attribute[:no_view] = true
|
250
|
-
@encrypt_on_set = true
|
251
|
-
end
|
252
|
-
|
253
|
-
def form_to_value(val)
|
254
|
-
return encrypt_value(val)
|
255
281
|
end
|
256
282
|
|
257
283
|
def encrypt_value(val)
|
@@ -260,13 +286,15 @@ module Ezframe
|
|
260
286
|
end
|
261
287
|
|
262
288
|
def value_equal?(value_from_db, new_value)
|
263
|
-
|
264
|
-
return
|
289
|
+
crypt = BCrypt::Password.new(value_from_db)
|
290
|
+
return crypt == new_value
|
265
291
|
end
|
266
292
|
|
267
293
|
def form(opts = {})
|
268
294
|
return nil if no_edit? && !opts[:force]
|
269
|
-
|
295
|
+
key = self.key
|
296
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
297
|
+
h = { tag: "input", type: "password", name: key, label: @attribute[:label], value: "" }
|
270
298
|
h[:class] = @attribute[:class] if @attribute[:class]
|
271
299
|
return h
|
272
300
|
end
|
@@ -280,8 +308,8 @@ module Ezframe
|
|
280
308
|
class SelectType < TypeBase
|
281
309
|
def form(opts = {})
|
282
310
|
return nil if no_edit? && !opts[:force]
|
283
|
-
|
284
|
-
h = { tag: "select", class: %w[browser-default], name: self.key, label: @attribute[:label], item: @
|
311
|
+
@items ||= @attribute[:item]
|
312
|
+
h = { tag: "select", class: %w[browser-default], name: self.key, label: @attribute[:label], item: @items, value: @value }
|
285
313
|
h[:class] = @attribute[:class] if @attribute[:class]
|
286
314
|
return h
|
287
315
|
end
|
@@ -293,7 +321,7 @@ module Ezframe
|
|
293
321
|
def view(opts = {})
|
294
322
|
return nil if no_view? && !opts[:force]
|
295
323
|
item = @attribute[:item]
|
296
|
-
#
|
324
|
+
# EzLog.debug("select.view: @value=#{@value}, #{@value.class}, item=#{item}, result=#{item[@value]}")
|
297
325
|
return nil unless @value
|
298
326
|
return item[@value.to_s.to_sym]
|
299
327
|
end
|
@@ -306,7 +334,9 @@ module Ezframe
|
|
306
334
|
class CheckboxType < TypeBase
|
307
335
|
def form(opts = {})
|
308
336
|
return nil if no_edit? && !opts[:force]
|
309
|
-
|
337
|
+
key = self.key
|
338
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
339
|
+
h = Ht.checkbox(name: key, value: parent[:id].value, label: @attribute[:label])
|
310
340
|
h[:class] = @attribute[:class] if @attribute[:class]
|
311
341
|
return h
|
312
342
|
end
|
@@ -331,7 +361,7 @@ module Ezframe
|
|
331
361
|
end
|
332
362
|
|
333
363
|
def db_type
|
334
|
-
"date"
|
364
|
+
return "date"
|
335
365
|
end
|
336
366
|
|
337
367
|
def value
|
@@ -364,7 +394,7 @@ module Ezframe
|
|
364
394
|
if v.is_a?(Date) || v.is_a?(Time)
|
365
395
|
@value = v
|
366
396
|
else
|
367
|
-
|
397
|
+
EzLog.info "[WARN] illegal value for date type: #{v.inspect}"
|
368
398
|
end
|
369
399
|
end
|
370
400
|
|
@@ -412,8 +442,8 @@ module Ezframe
|
|
412
442
|
end
|
413
443
|
begin
|
414
444
|
@value = DateTime.parse(v)
|
415
|
-
rescue
|
416
|
-
|
445
|
+
rescue => e
|
446
|
+
EzLog.warn("date format error: #{self.key}=#{v}:#{e}")
|
417
447
|
@value = nil
|
418
448
|
end
|
419
449
|
return
|
@@ -421,7 +451,7 @@ module Ezframe
|
|
421
451
|
if v.is_a?(Date) || v.is_a?(Time) || v.is_a?(DateTime)
|
422
452
|
@value = v
|
423
453
|
else
|
424
|
-
|
454
|
+
EzLog.info "[WARN] illegal value for date type: #{v.inspect}"
|
425
455
|
end
|
426
456
|
end
|
427
457
|
|
@@ -439,7 +469,7 @@ module Ezframe
|
|
439
469
|
end
|
440
470
|
|
441
471
|
def form(opts = {})
|
442
|
-
|
472
|
+
# EzLog.debug("DatetimeType: key=#{self.key}, opts=#{opts}")
|
443
473
|
return nil if no_edit? && !opts[:force]
|
444
474
|
h = super
|
445
475
|
if h
|
@@ -449,7 +479,7 @@ module Ezframe
|
|
449
479
|
h[:class] = [ "datepicker" ]
|
450
480
|
h[:class].push(@attribute[:class]) if @attribute[:class]
|
451
481
|
end
|
452
|
-
|
482
|
+
# EzLog.debug("DatetimeType: res=#{h}")
|
453
483
|
return h
|
454
484
|
end
|
455
485
|
|
@@ -467,7 +497,6 @@ module Ezframe
|
|
467
497
|
class BirthdayType < TextType
|
468
498
|
def form(opts = {})
|
469
499
|
return nil if no_edit? && !opts[:force]
|
470
|
-
prefix = self.key
|
471
500
|
now = Time.now
|
472
501
|
year_list = []
|
473
502
|
110.times do |y|
|
@@ -476,16 +505,19 @@ module Ezframe
|
|
476
505
|
end
|
477
506
|
year_list.unshift([ 0, "(年)" ])
|
478
507
|
|
508
|
+
key = self.key
|
509
|
+
key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
|
510
|
+
|
479
511
|
year, mon, mday = parse_date(@value)
|
480
512
|
mon_list = (1..12).map { |m| [m, "#{m}"] }
|
481
513
|
mon_list.unshift([0, "(月)"])
|
482
514
|
mday_list = (1..31).map { |d| [d, "#{d}"] }
|
483
515
|
mday_list.unshift([0, "(日)"])
|
484
|
-
return [Ht.div([Ht.select(name: "#{
|
516
|
+
return [Ht.div([Ht.select(name: "#{key}_year", class: %w[browser-default], item: year_list, value: year),
|
485
517
|
Ht.small("年")]),
|
486
|
-
Ht.select(name: "#{
|
518
|
+
Ht.select(name: "#{key}_mon", class: %w[browser-default], item: mon_list, value: mon),
|
487
519
|
Ht.small("月"),
|
488
|
-
Ht.select(name: "#{
|
520
|
+
Ht.select(name: "#{key}_mday", class: %w[browser-default], item: mday_list, value: mday),
|
489
521
|
Ht.small("日")
|
490
522
|
]
|
491
523
|
end
|
@@ -511,8 +543,9 @@ module Ezframe
|
|
511
543
|
true
|
512
544
|
end
|
513
545
|
|
514
|
-
def form_to_value(form)
|
515
|
-
|
546
|
+
def form_to_value(form, target_key: nil)
|
547
|
+
key = target_key || self.key
|
548
|
+
y, m, d = form["#{key}_year".to_sym], form["#{key}_mon".to_sym], form["#{key}_mday".to_sym]
|
516
549
|
return "%d-%02d-%02d"%[y.to_i, m.to_i, d.to_i]
|
517
550
|
end
|
518
551
|
end
|
@@ -568,6 +601,9 @@ module Ezframe
|
|
568
601
|
end
|
569
602
|
end
|
570
603
|
|
604
|
+
class UrlType < TextType
|
605
|
+
end
|
606
|
+
|
571
607
|
class JpnameType < TextType
|
572
608
|
end
|
573
609
|
|
@@ -611,7 +647,7 @@ module Ezframe
|
|
611
647
|
class PrefectureType < SelectType
|
612
648
|
attr_accessor :pref_h
|
613
649
|
|
614
|
-
def initialize(attr)
|
650
|
+
def initialize(attr = nil)
|
615
651
|
super(attr)
|
616
652
|
@pref_a = %w[() 北海道 青森県 岩手県 宮城県 秋田県 山形県 福島県
|
617
653
|
茨城県 栃木県 群馬県 埼玉県 千葉県 東京都 神奈川県
|
@@ -631,7 +667,7 @@ module Ezframe
|
|
631
667
|
return h
|
632
668
|
end
|
633
669
|
|
634
|
-
def view
|
670
|
+
def view(opts = {})
|
635
671
|
return nil if no_view? && !opts[:force]
|
636
672
|
return @pref_h[@value.to_i]
|
637
673
|
end
|
data/lib/ezframe/config.rb
CHANGED
@@ -30,13 +30,13 @@ module Ezframe
|
|
30
30
|
instr = Template.fill_in_text(instr)
|
31
31
|
end
|
32
32
|
begin
|
33
|
-
yaml = YAML.load(instr)
|
34
|
-
rescue
|
35
|
-
|
33
|
+
yaml = YAML.load(instr, symbolize_names: true)
|
34
|
+
rescue => e
|
35
|
+
EzLog.info("YAML load error: #{filename}:#{e}")
|
36
36
|
return
|
37
37
|
end
|
38
38
|
@value_h ||={}
|
39
|
-
@value_h.update(yaml
|
39
|
+
@value_h.update(yaml) if yaml.length>0 # .recursively_symbolize_keys
|
40
40
|
end
|
41
41
|
|
42
42
|
def [](k)
|
data/lib/ezframe/controller.rb
CHANGED
@@ -14,7 +14,7 @@ module Ezframe
|
|
14
14
|
@request = request
|
15
15
|
page_instance, method, url_params, class_opts = Route::choose(request)
|
16
16
|
|
17
|
-
|
17
|
+
EzLog.debug("Controller.exec: path=#{request.path_info}, params=#{request.params}, class=#{page_instance.class}, method=#{method}, url_params=#{url_params}, class_opts=#{class_opts}")
|
18
18
|
if !page_instance || page_instance == 404
|
19
19
|
file_not_found(response)
|
20
20
|
return
|
@@ -23,18 +23,18 @@ module Ezframe
|
|
23
23
|
opt_auth = class_opts[:auth]
|
24
24
|
@session = @request.env['rack.session']
|
25
25
|
if !@session[:user] && Config[:auth] && (!opt_auth || opt_auth != "disable")
|
26
|
-
|
26
|
+
EzLog.debug("authenticate!")
|
27
27
|
warden.authenticate!
|
28
|
-
|
28
|
+
EzLog.info "Controller.exec: warden.options = #{@request.env['warden.options']}"
|
29
29
|
end
|
30
30
|
# session["in_controller"] = "set in controller"
|
31
|
-
|
31
|
+
EzLog.debug "rack.session.keys=#{@session.keys}" if @session
|
32
32
|
page_instance.set_request(@request)
|
33
33
|
body = page_instance.send(method)
|
34
34
|
|
35
35
|
# 戻り値によるレスポンス生成
|
36
36
|
if body.is_a?(Hash) || body.is_a?(Array)
|
37
|
-
#
|
37
|
+
# EzLog.debug("Controller: body = #{body}")
|
38
38
|
json = JSON.generate(body)
|
39
39
|
response.body = [ json ]
|
40
40
|
response['Content-Type'] = 'application/json; charset=utf-8'
|
@@ -43,7 +43,7 @@ module Ezframe
|
|
43
43
|
response['Content-Type'] = 'text/html; charset=utf-8'
|
44
44
|
end
|
45
45
|
response.status = 200
|
46
|
-
#
|
46
|
+
# EzLog.debug("Controller.exec: response.body=#{response.body}")
|
47
47
|
end
|
48
48
|
|
49
49
|
def file_not_found(response)
|
data/lib/ezframe/database.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require "logger"
|
3
|
-
|
4
2
|
module Ezframe
|
5
3
|
class DB
|
6
4
|
class << self
|
@@ -8,9 +6,12 @@ module Ezframe
|
|
8
6
|
|
9
7
|
def init(dbfile = nil, opts = {})
|
10
8
|
@dbfile = dbfile || ENV["EZFRAME_DB"] || Config[:database]
|
9
|
+
unless @dbfile
|
10
|
+
raise "database settings error: dbfile=#{Config[:database]}"
|
11
|
+
end
|
11
12
|
if Config[:use_connection_pool] || opts[:use_connection_pool]
|
12
13
|
@pool = Sequel::ConnectionPool(max_connections: 10) do
|
13
|
-
Sequel.connect(@dbfile, loggers: [
|
14
|
+
Sequel.connect(@dbfile, loggers: [EzLog])
|
14
15
|
end
|
15
16
|
else
|
16
17
|
connect(@dbfile)
|
@@ -19,7 +20,7 @@ module Ezframe
|
|
19
20
|
|
20
21
|
def connect(dbfile = nil)
|
21
22
|
dbfile ||= @dbfile
|
22
|
-
@sequel = Sequel.connect(dbfile,
|
23
|
+
@sequel = Sequel.connect(dbfile, EzLogs: [EzLog])
|
23
24
|
return @sequel
|
24
25
|
end
|
25
26
|
|
@@ -117,7 +118,7 @@ module Ezframe
|
|
117
118
|
|
118
119
|
# テーブル生成
|
119
120
|
def create_table(table_name, dbtype_h)
|
120
|
-
%w[id created_at updated_at].each do |key|
|
121
|
+
%w[id created_at updated_at deleted_at].each do |key|
|
121
122
|
dbtype_h.delete(key.to_sym)
|
122
123
|
end
|
123
124
|
# puts "create_table: #{table_name}"
|
@@ -128,7 +129,8 @@ module Ezframe
|
|
128
129
|
column(key, dbtype)
|
129
130
|
end
|
130
131
|
column(:created_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
|
131
|
-
column(:updated_at, :timestamp
|
132
|
+
column(:updated_at, :timestamp)
|
133
|
+
column(:deleted_at, :timestamp)
|
132
134
|
end
|
133
135
|
else
|
134
136
|
@sequel.create_table(table_name) do
|
@@ -137,7 +139,8 @@ module Ezframe
|
|
137
139
|
column(key, dbtype)
|
138
140
|
end
|
139
141
|
column(:created_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
|
140
|
-
column(:updated_at, :timestamp
|
142
|
+
column(:updated_at, :timestamp)
|
143
|
+
column(:deleted_at, :timestamp)
|
141
144
|
end
|
142
145
|
end
|
143
146
|
end
|
@@ -146,9 +149,13 @@ module Ezframe
|
|
146
149
|
dataset(table_name).insert(val_h)
|
147
150
|
end
|
148
151
|
|
149
|
-
def update(dataset, val_h)
|
150
|
-
val_h.update({ updated_at: Time.now
|
151
|
-
dataset.update(val_h)
|
152
|
+
def update(dataset, id, val_h)
|
153
|
+
val_h.update({ updated_at: Time.now })
|
154
|
+
dataset.where(id: id).update(val_h)
|
155
|
+
end
|
156
|
+
|
157
|
+
def delete(dataset, id)
|
158
|
+
dataset.where(id: id).update({ deleted_at: Time.now })
|
152
159
|
end
|
153
160
|
end
|
154
161
|
|
@@ -158,14 +165,14 @@ module Ezframe
|
|
158
165
|
def [](table)
|
159
166
|
@store ||= {}
|
160
167
|
dataset = DB.dataset(table.to_sym)
|
161
|
-
#
|
168
|
+
# EzLog.debug("DB::Cache: #{table}")
|
162
169
|
unless @store[table.to_sym]
|
163
|
-
data_a = dataset.all
|
170
|
+
data_a = dataset.where(deleted_at: nil).all
|
164
171
|
h = {}
|
165
172
|
data_a.each {|data| h[data[:id]] = data }
|
166
173
|
@store[table.to_sym] = h
|
167
174
|
end
|
168
|
-
#
|
175
|
+
# EzLog.debug(@store[table.to_sym])
|
169
176
|
return @store[table.to_sym]
|
170
177
|
end
|
171
178
|
end
|