ezframe 0.3.0 → 0.4.0

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