ezframe 0.3.0 → 0.4.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.
@@ -51,8 +51,12 @@ module Ezframe
51
51
  end
52
52
 
53
53
  def parse_create_sql(sql)
54
- sql.gsub(/CREATE TABLE \`(\w+)\` \(/i, "")
55
- table_name = $1
54
+ # EzLog.debug("parse_create_sql: #{sql}")
55
+ if sql =~ /CREATE TABLE \`(\w+)\` \(/i
56
+ table_name = $1
57
+ else
58
+ return
59
+ end
56
60
  @db_columns[table_name.to_sym] ||= {}
57
61
  column_a = sql.split(", ")
58
62
  column_a.each do |line|
@@ -114,17 +118,47 @@ module Ezframe
114
118
  end
115
119
  if dbtype != new_type
116
120
  exec_sql("ALTER TABLE #{table_name} ALTER COLUMN #{column.key} DROP DEFAULT;")
117
- begin
118
- exec_sql("ALTER TABLE #{table_name} ALTER #{column.key} TYPE #{new_type};")
119
- rescue => e
120
- EzLog.error("alter column type error: #{e.class}:#{e}:#{e.backtrace}")
121
- back_key = "#{column.key}_bak"
122
- exec_sql("ALTER TABLE #{table_name} RENAME #{column.key} TO #{back_key};")
121
+ unless change_type(table, column.key, new_type)
122
+ # 失敗したときは名前を変更してカラム追加
123
+ rename_column(table_name, column.key, "#{column.key}_bak")
124
+ add_column(table, column.key, new_type)
123
125
  end
124
126
  set_default(column)
125
127
  end
126
128
  end
127
- # exec_sql("ALTER TABLE #{table_name} add COLUMN deleted_at timestamp;")
129
+ end
130
+
131
+ # カラム追加
132
+ def add_column(table_name, key, typ)
133
+ begin
134
+ exec_sql("ALTER TABLE #{table_name} ADD #{key} #{typ};")
135
+ rescue => e
136
+ EzLog.error("change_type: error: #{e.class}:#{e}:#{e.backtrace}")
137
+ return nil
138
+ end
139
+ return true
140
+ end
141
+
142
+ # カラムの型変更
143
+ def change_type(table_name, key, typ)
144
+ begin
145
+ exec_sql("ALTER TABLE #{table_name} ALTER #{key} TYPE #{typ};")
146
+ rescue => e
147
+ EzLog.error("change_type: error: #{e.class}:#{e}:#{e.backtrace}")
148
+ return nil
149
+ end
150
+ return true
151
+ end
152
+
153
+ # カラムの名前変更
154
+ def rename_column(table_name, old_key, new_key)
155
+ begin
156
+ exec_sql("ALTER TABLE #{table_name} RENAME #{old_key} TO #{new_key};")
157
+ rescue => e
158
+ EzLog.error("rename_column: error: #{e.class}:#{e}:#{e.backtrace}")
159
+ return nil
160
+ end
161
+ return true
128
162
  end
129
163
  end
130
164
  end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ #coding: utf-8
3
+ =begin
4
+
5
+ HTMLから、hthash生成するrubyプログラムを生成する
6
+
7
+ =end
8
+ require "nokogiri"
9
+
10
+ class Html2Ruby
11
+ def show_leaves(node, depth=0)
12
+ res = []
13
+ indent = " "*depth
14
+ node.children.each do |child|
15
+ next if child.name == "comment"
16
+ if child.name == "text"
17
+ if child.content.strip.empty?
18
+ next
19
+ else
20
+ res.push "#{indent}\"#{child.content}\""
21
+ end
22
+ else
23
+ attrs = child.attributes.map do |k, v|
24
+ if k.index("-")
25
+ key_s = "\"#{k}\""
26
+ else
27
+ key_s = k
28
+ if k == "class"
29
+ if v =~/\s/
30
+ cls_a = v.split(/\s+/)
31
+ v = "%w[#{cls_a.join(' ')}]"
32
+ end
33
+ end
34
+ end
35
+ "#{key_s}: \"#{v}\""
36
+ end
37
+ descendant = show_leaves(child, depth+1)
38
+ if descendant && descendant.strip.length > 10
39
+ attrs.push("child: \n#{descendant}\n")
40
+ res.push "#{indent}Ht.#{child.name}(#{attrs.join(', ')}#{indent})"
41
+ else
42
+ res.push "#{indent}Ht.#{child.name}(#{attrs.join(', ')})"
43
+ end
44
+ end
45
+ end
46
+ if res.length > 1
47
+ res_s = res.join(",\n")
48
+ return "[ #{res_s} ]"
49
+ else
50
+ return res[0]
51
+ end
52
+ end
53
+
54
+ def show_all(file)
55
+ doc = Nokogiri::HTML(File.open(file))
56
+ puts show_leaves(doc.root)
57
+ end
58
+ end
59
+
60
+ node = Html2Ruby.new
61
+ node.show_all(ARGV[0])
@@ -28,7 +28,6 @@ require_relative 'ezframe/template'
28
28
  require_relative 'ezframe/server'
29
29
  require_relative 'ezframe/message'
30
30
  require_relative 'ezframe/auth.rb'
31
- require_relative 'ezframe/editor.rb'
32
31
  require_relative 'ezframe/loader'
33
32
  require_relative 'ezframe/route'
34
33
 
@@ -108,6 +108,10 @@ module Ezframe
108
108
  return pattern % value_a
109
109
  end
110
110
  end
111
+
112
+ def make_error_box(name)
113
+ Ht.div(id: "error-box-#{name}", class: %w[error-box hide], child: "")
114
+ end
111
115
  end
112
116
 
113
117
  class TextType < TypeBase
@@ -130,6 +134,7 @@ module Ezframe
130
134
  key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
131
135
  h = Ht.input(type: "text", name: key, label: @attribute[:label], value: @value || "")
132
136
  h[:class] = @attribute[:class] if @attribute[:class]
137
+ h[:after] = make_error_box(key)
133
138
  return h
134
139
  end
135
140
 
@@ -151,6 +156,7 @@ module Ezframe
151
156
  key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
152
157
  h = Ht.textarea(name: key, label: @attribute[:label], child: val)
153
158
  h[:class] = @attribute[:class] if @attribute[:class]
159
+ h[:after] = make_error_box(key)
154
160
  return h
155
161
  end
156
162
  end
@@ -207,6 +213,7 @@ module Ezframe
207
213
  key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
208
214
  h = Ht.input(type: "number", name: key, label: @attribute[:label], value: @value || "")
209
215
  h[:class] = @attribute[:class] if @attribute[:class]
216
+ h[:after] = make_error_box(key)
210
217
  return h
211
218
  end
212
219
 
@@ -253,7 +260,7 @@ module Ezframe
253
260
  end
254
261
  key = self.key
255
262
  key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
256
- return Ht.select(name: key, class: %w[browser-default], item: menu_a, value: @value)
263
+ return Ht.select(name: key, class: %w[browser-default], item: menu_a, value: @value, after: make_error_box(key))
257
264
  end
258
265
 
259
266
  def db_type
@@ -294,9 +301,10 @@ module Ezframe
294
301
  return nil if no_edit? && !opts[:force]
295
302
  key = self.key
296
303
  key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
297
- h = { tag: "input", type: "password", name: key, label: @attribute[:label], value: "" }
304
+ h = Ht.input(type: "password", name: key, label: @attribute[:label], value: "")
298
305
  h[:class] = @attribute[:class] if @attribute[:class]
299
- return h
306
+ h[:after] = make_error_box(key)
307
+ return h
300
308
  end
301
309
 
302
310
  def db_value
@@ -309,8 +317,9 @@ module Ezframe
309
317
  def form(opts = {})
310
318
  return nil if no_edit? && !opts[:force]
311
319
  @items ||= @attribute[:item]
312
- h = { tag: "select", class: %w[browser-default], name: self.key, label: @attribute[:label], item: @items, value: @value }
320
+ h = Ht.select(class: %w[browser-default], name: self.key, label: @attribute[:label], item: @items, value: @value)
313
321
  h[:class] = @attribute[:class] if @attribute[:class]
322
+ h[:after] = make_error_box(self.key)
314
323
  return h
315
324
  end
316
325
 
@@ -338,6 +347,7 @@ module Ezframe
338
347
  key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
339
348
  h = Ht.checkbox(name: key, value: parent[:id].value, label: @attribute[:label])
340
349
  h[:class] = @attribute[:class] if @attribute[:class]
350
+ h[:after] = make_error_box(key)
341
351
  return h
342
352
  end
343
353
 
@@ -350,6 +360,7 @@ module Ezframe
350
360
  def form(opts = {})
351
361
  return nil if no_edit? && !opts[:force]
352
362
  h = super
363
+ return nil unless h
353
364
  if h
354
365
  # h[:type] = 'date'
355
366
  h[:type] = "text"
@@ -422,7 +433,8 @@ module Ezframe
422
433
  class DatetimeType < TextType
423
434
  def initialize(attr = nil)
424
435
  super(attr)
425
- @attribute[:class] = "datetimepicker"
436
+ # @attribute[:class] = "datettimepicker" # for jquery datetimepicker
437
+ @attribute[:class] = "datetpicker"
426
438
  end
427
439
 
428
440
  def value=(v)
@@ -472,14 +484,13 @@ module Ezframe
472
484
  # EzLog.debug("DatetimeType: key=#{self.key}, opts=#{opts}")
473
485
  return nil if no_edit? && !opts[:force]
474
486
  h = super
487
+ return nil unless h
475
488
  if h
476
- # h[:type] = 'date'
477
489
  h[:type] = "text"
478
490
  h[:value] = @value || ""
479
491
  h[:class] = [ "datepicker" ]
480
492
  h[:class].push(@attribute[:class]) if @attribute[:class]
481
493
  end
482
- # EzLog.debug("DatetimeType: res=#{h}")
483
494
  return h
484
495
  end
485
496
 
@@ -513,13 +524,15 @@ module Ezframe
513
524
  mon_list.unshift([0, "(月)"])
514
525
  mday_list = (1..31).map { |d| [d, "#{d}"] }
515
526
  mday_list.unshift([0, "(日)"])
516
- return [Ht.div([Ht.select(name: "#{key}_year", class: %w[browser-default], item: year_list, value: year),
527
+ ezvalid = "target_key=#{key}:with=#multi-#{key}"
528
+ return Ht.div(id: "multi-#{key}",
529
+ child: [ Ht.div([Ht.select(name: "#{key}_year", class: %w[browser-default multi_input], item: year_list, value: year, ezvalid: ezvalid),
517
530
  Ht.small("年")]),
518
- Ht.select(name: "#{key}_mon", class: %w[browser-default], item: mon_list, value: mon),
531
+ Ht.select(name: "#{key}_mon", class: %w[browser-default multi_input], item: mon_list, value: mon, ezvalid: ezvalid),
519
532
  Ht.small("月"),
520
- Ht.select(name: "#{key}_mday", class: %w[browser-default], item: mday_list, value: mday),
521
- Ht.small("日")
522
- ]
533
+ Ht.select(name: "#{key}_mday", class: %w[browser-default multi_input], item: mday_list, value: mday, ezvalid: ezvalid),
534
+ Ht.small("日"),
535
+ make_error_box(key)])
523
536
  end
524
537
 
525
538
  def view(opts = {})
@@ -548,13 +561,36 @@ module Ezframe
548
561
  y, m, d = form["#{key}_year".to_sym], form["#{key}_mon".to_sym], form["#{key}_mday".to_sym]
549
562
  return "%d-%02d-%02d"%[y.to_i, m.to_i, d.to_i]
550
563
  end
564
+
565
+ def validate(val)
566
+ return validate_date(val)
567
+ end
568
+
569
+ # 日付の検証
570
+ def validate_date(val)
571
+ if val.is_a?(String)
572
+ y,m,d = val.split("-")
573
+ if y.to_i == 0 || m.to_i == 0 || d.to_i == 0
574
+ return nil
575
+ end
576
+ tm = Time.mktime(y.to_i, m.to_i, d.to_i)
577
+ elsif val.is_a?(Time)
578
+ tm = val
579
+ end
580
+ if tm.mday != d.to_i
581
+ @error = :invalid_value
582
+ return @error
583
+ end
584
+ return nil
585
+ end
551
586
  end
552
587
 
553
588
  class EmailType < TextType
554
589
  def form(opts = {})
555
590
  return nil if no_edit? && !opts[:force]
556
591
  h = super
557
- h[:type] = "email" if h
592
+ return nil unless h
593
+ h[:type] = "email"
558
594
  h[:class] = @attribute[:class] if @attribute[:class]
559
595
  return h
560
596
  end
@@ -663,6 +699,7 @@ module Ezframe
663
699
  def form(opts = {})
664
700
  return nil if no_edit? && !opts[:force]
665
701
  h = super
702
+ return nil unless h
666
703
  h[:item] = @pref_h
667
704
  return h
668
705
  end
@@ -9,13 +9,13 @@ module Ezframe
9
9
  unless @dbfile
10
10
  raise "database settings error: dbfile=#{Config[:database]}"
11
11
  end
12
- if Config[:use_connection_pool] || opts[:use_connection_pool]
13
- @pool = Sequel::ConnectionPool(max_connections: 10) do
14
- Sequel.connect(@dbfile, loggers: [EzLog])
15
- end
16
- else
17
- connect(@dbfile)
18
- end
12
+ #if Config[:use_connection_pool] || opts[:use_connection_pool]
13
+ #@pool = Sequel::ConnectionPool.new(max_connections: 10) do
14
+ # Sequel.connect(@dbfile, loggers: [EzLog])
15
+ #end
16
+ #else
17
+ connect(@dbfile)
18
+ #end
19
19
  end
20
20
 
21
21
  def connect(dbfile = nil)
@@ -3,39 +3,56 @@ module Ezframe
3
3
  def get_id(class_name = nil)
4
4
  class_name ||= @class_snake
5
5
  params = @request.env['url_params']
6
+ return nil unless params
6
7
  # EzLog.info "get_id: #{params.inspect}, #{class_name}"
7
8
  return params[class_name.to_sym]
8
9
  end
9
10
 
11
+ # 新規データの生成
12
+ def create_data(form)
13
+ @column_set.clear
14
+ @column_set[:id].value = id = @column_set.create(form)
15
+ return id
16
+ end
17
+
18
+ # データの更新
19
+ def update_data(id, form)
20
+ @column_set.update(id, form)
21
+ end
22
+
23
+ def make_form(url, child)
24
+ return Ht.form(ezload: "command=set_validation:validate_url=#{url}", child: child)
25
+ end
26
+
10
27
  # 新規登録ボタンの生成
11
28
  def make_create_button(event = nil)
12
29
  event ||= "on=click:url=#{make_base_url(@id)}/create"
13
- return Ht.button(id: "#{@class_snake}-create-button", class: %[btn], child: [Ht.icon("add"), Message[:create_button_label]], event: event)
30
+ return Ht.button(id: "#{@class_snake}-create-button", class: %[btn], child: [Ht.icon("add"), Message[:create_button_label]], ezevent: event)
14
31
  end
15
32
 
16
33
  # 編集ボタンの生成
17
34
  def make_edit_button(event = nil)
18
35
  event ||= "on=click:url=#{make_base_url(@id)}/edit"
19
- return Ht.button(class: %w[btn], event: event, child: [ Ht.icon("edit"), Message[:edit_button_label]])
36
+ return Ht.button(class: %w[btn], ezevent: event, child: [ Ht.icon("edit"), Message[:edit_button_label]])
20
37
  end
21
38
 
22
39
  # 削除ボタンの生成
23
40
  def make_delete_button(event = nil)
24
41
  event ||= "on=click:url=#{make_base_url(@id)}/delete"
25
- return Ht.button(class: %w[btn right red], event: event, child: [Ht.icon("delete"), Message[:delete_button_label]])
42
+ return Ht.button(class: %w[btn right red], ezevent: event, child: [Ht.icon("delete"), Message[:delete_button_label]])
26
43
  end
27
44
 
28
45
  # キャンセルボタンの生成
29
46
  def make_cancel_button(event = nil)
30
47
  event ||= "on=click:url=#{make_base_url(@id)}/detail:cancel=true:with=form"
31
- return Ht.button(class: %w[btn red], child: [Ht.icon("cancel"), Message[:cancel_button_label]], event: event)
48
+ return Ht.button(class: %w[btn red], child: [Ht.icon("cancel"), Message[:cancel_button_label]], ezevent: event)
32
49
  end
33
50
 
34
51
  # 値の更新
35
- def update_value
36
- form = @event[:form]
37
- @column_set.update(get_id, form)
38
- end
52
+ # def update_value
53
+ # form = @event[:form]
54
+ # @column_set.update(get_id, form)
55
+ # end
39
56
 
40
57
  # ラベル付きで1カラムのviewを表示
41
58
  def show_label_view(key)
@@ -49,6 +66,7 @@ module Ezframe
49
66
  Ht.span([Ht.small(col.label), col.form(force: true)])
50
67
  end
51
68
 
69
+ # エラーメッセージだけを表示するページを生成
52
70
  def show_message_page(title, body)
53
71
  return show_base_template(title: title, body: Html.convert(body))
54
72
  end
@@ -18,6 +18,7 @@ module Ezframe
18
18
  return nil
19
19
  end
20
20
  h[:tag] ||= __callee__.to_s
21
+ h[:wrap] = true
21
22
  raise "no tag" if h[:tag] == "wrap_tag"
22
23
  return h
23
24
  end
@@ -58,6 +59,7 @@ module Ezframe
58
59
  alias_method :form, :wrap_tag
59
60
  alias_method :input, :single_tag
60
61
  alias_method :select, :wrap_tag
62
+ alias_method :option, :wrap_tag
61
63
  alias_method :textarea, :wrap_tag
62
64
  alias_method :label, :wrap_tag
63
65
  alias_method :fieldset, :wrap_tag
@@ -79,7 +81,7 @@ module Ezframe
79
81
  h[:tag] = "icon"
80
82
  return wrap_tag(h)
81
83
  elsif arg.is_a?(String)
82
- return { tag: "icon", name: arg }
84
+ return { tag: "icon", wrap: true, name: arg }
83
85
  end
84
86
  end
85
87
 
@@ -120,10 +122,8 @@ module Ezframe
120
122
  attr_accessor :tag
121
123
  def to_h(opts = {})
122
124
  return nil if self.empty?
123
- child = self.map do |elem|
124
- { tag: "li", child: elem }
125
- end
126
- h = { tag: @tag, child: child }
125
+ child = self.map { |elem| Ht.li(elem) }
126
+ h = { tag: @tag, wrap: true, child: child }
127
127
  h.update(opts)
128
128
  return h
129
129
  end
@@ -20,24 +20,30 @@ module Ezframe
20
20
  tag = "i"
21
21
  end
22
22
  tag = ht_h[:tag]
23
- error_box = ""
24
- if %w[input select textarea].include?(tag)
25
- error_box = "<div id=\"error-box-#{ht_h[:name]}\" class=\"error-box hide\"></div>"
23
+ join_info = join_attribute(ht_h)
24
+ start_tag = [ht_h[:tag], join_info[:attr]].compact.join(" ").strip
25
+ if ht_h[:wrap] # !child_s.strip.empty? ||
26
+ return "#{join_info[:before]}<#{start_tag}>#{join_info[:child]}</#{ht_h[:tag]}>#{join_info[:after]}"
26
27
  end
27
- opt_s, child_s = join_attribute(ht_h)
28
- if !child_s.strip.empty? || !%w[img input hr br meta].include?(tag)
29
- start_tag = [ht_h[:tag], opt_s].compact.join(" ").strip
30
- return "<#{start_tag}>#{child_s}</#{ht_h[:tag]}>"+error_box
31
- end
32
- tag_content = [ ht_h[:tag], opt_s ].compact.join(" ")
33
- return "<#{tag_content}/>"+error_box
28
+ # tag_content = [ ht_h[:tag], join_info[:attr] ].compact.join(" ")
29
+ return "#{join_info[:before]}<#{start_tag}/>#{join_info[:after]}"
34
30
  end
35
31
 
36
32
  # attributeの連結文字列化
37
33
  def join_attribute(attrs)
38
34
  child_s = ""
35
+ before = ""
36
+ after = ""
39
37
  opt_a = attrs.map do |k, v|
40
38
  case k
39
+ when :before
40
+ before = convert(v)
41
+ next
42
+ when :after
43
+ after = convert(v)
44
+ next
45
+ when :wrap
46
+ nil
41
47
  when :child
42
48
  child_s = convert(v)
43
49
  next
@@ -56,7 +62,7 @@ module Ezframe
56
62
  end
57
63
  end
58
64
  end
59
- [opt_a.compact.join(" "), child_s]
65
+ { attr: opt_a.compact.join(" "), before: before, after: after, child: child_s }
60
66
  end
61
67
 
62
68
  def textarea(ht_h)
@@ -73,7 +79,7 @@ module Ezframe
73
79
  # puts "Html.select: #{item}"
74
80
  if item.is_a?(Hash)
75
81
  option_a = ht_h[:item].map do |k, v|
76
- h = { tag: "option", value: k }
82
+ h = Ht.option(value: k)
77
83
  if v.is_a?(Array)
78
84
  v, selected = v
79
85
  h[:selected] = "selected" if selected
@@ -87,7 +93,7 @@ module Ezframe
87
93
  end
88
94
  elsif item.is_a?(Array)
89
95
  option_a = item.map do |v|
90
- h = { tag: "option", value: v[0], child: v[1] }
96
+ h = Ht.option(value: v[0], child: v[1])
91
97
  if %w[selected default].include?(v[2])
92
98
  h[:selected] = "selected"
93
99
  end
@@ -105,6 +111,7 @@ module Ezframe
105
111
  attr[:child] = option_a
106
112
  attr[:name] ||= attr[:key]
107
113
  attr[:final] = true
114
+ attr[:wrap] = true
108
115
  attr.delete(:item)
109
116
  Html.convert(attr)
110
117
  end