ezframe 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|