ezframe 0.0.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +1 -1
  4. data/asset/css/materialize.min.css +13 -0
  5. data/asset/css/style.css +3 -0
  6. data/asset/html/index.html +1 -0
  7. data/{app_template/asset/image/favicon.ico → asset/image/c_e.ico} +0 -0
  8. data/asset/js/ezframe.js +387 -0
  9. data/exe/check_column_yml +64 -0
  10. data/exe/console +2 -2
  11. data/exe/{create_table.rb → create_table} +7 -4
  12. data/exe/dbmigrate +174 -0
  13. data/exe/html2ruby +61 -0
  14. data/ezframe.gemspec +10 -8
  15. data/lib/ezframe.rb +9 -3
  16. data/lib/ezframe/auth.rb +50 -31
  17. data/lib/ezframe/column_set.rb +314 -103
  18. data/lib/ezframe/column_type.rb +456 -99
  19. data/lib/ezframe/config.rb +27 -6
  20. data/lib/ezframe/controller.rb +41 -38
  21. data/lib/ezframe/database.rb +171 -52
  22. data/lib/ezframe/editor_common.rb +74 -0
  23. data/lib/ezframe/email.rb +34 -0
  24. data/lib/ezframe/ezlog.rb +40 -0
  25. data/lib/ezframe/ht.rb +42 -17
  26. data/lib/ezframe/html.rb +47 -31
  27. data/lib/ezframe/japanese_utils.rb +15 -0
  28. data/lib/ezframe/jquery-ui.rb +29 -0
  29. data/lib/ezframe/loader.rb +4 -4
  30. data/lib/ezframe/main_editor.rb +19 -0
  31. data/lib/ezframe/main_page_kit.rb +226 -0
  32. data/lib/ezframe/materialize.rb +10 -14
  33. data/lib/ezframe/message.rb +46 -0
  34. data/lib/ezframe/page_base.rb +59 -71
  35. data/lib/ezframe/route.rb +126 -0
  36. data/lib/ezframe/server.rb +16 -5
  37. data/lib/ezframe/single_page_editor.rb +22 -0
  38. data/lib/ezframe/single_page_kit.rb +199 -0
  39. data/lib/ezframe/sub_editor.rb +25 -0
  40. data/lib/ezframe/sub_page_kit.rb +213 -0
  41. data/lib/ezframe/template.rb +5 -4
  42. data/lib/ezframe/util.rb +45 -23
  43. data/lib/ezframe/version.rb +1 -1
  44. metadata +74 -34
  45. data/.rubocop.yml +0 -44
  46. data/app_template/asset/js/ezframe.js +0 -288
  47. data/app_template/config.ru +0 -10
  48. data/app_template/config/generic.yml +0 -3
  49. data/app_template/config/materialize.yml +0 -5
  50. data/app_template/pages/basic.rb +0 -5
  51. data/exe/setup.rb +0 -15
  52. data/lib/ezframe/editor.rb +0 -188
  53. data/lib/ezframe/model.rb +0 -52
  54. data/lib/ezframe/page_kit.rb +0 -63
@@ -9,8 +9,6 @@ module Ezframe
9
9
  return nil unless key
10
10
  upper = Object.const_get("Ezframe")
11
11
  key_camel = "#{key}_type".to_camel
12
- # puts "get_class: #{key_camel}"
13
- # puts "const_get: #{upper.const_get(key_camel).inspect}"
14
12
  if upper.const_defined?(key_camel)
15
13
  return upper.const_get(key_camel)
16
14
  end
@@ -26,17 +24,22 @@ module Ezframe
26
24
 
27
25
  def initialize(attr = nil)
28
26
  @attribute = attr || {}
27
+ @value = @attribute[:default]
29
28
  end
30
29
 
31
30
  def key
32
- @attribute[:key]
31
+ @attribute[:key].to_sym
33
32
  end
34
33
 
35
- def label
36
- return nil if @attribute[:hidden]
34
+ def label(opts = {})
35
+ return nil if @attribute[:hidden] && !opts[:force]
37
36
  @attribute[:label]
38
37
  end
39
38
 
39
+ def type
40
+ @attribute[:type]
41
+ end
42
+
40
43
  def value(_situation = nil)
41
44
  @value
42
45
  end
@@ -57,21 +60,23 @@ module Ezframe
57
60
  nil
58
61
  end
59
62
 
60
- def form_html(opts = {})
61
- form_h = form(opts)
62
- return nil unless form_h
63
- return Html.convert(form_h)
64
- end
65
-
66
63
  def view(opts = {})
67
64
  return nil if no_view?
68
- @value
65
+ if @attribute[:view_format]
66
+ return use_view_format(@attribute[:view_format], @value)
67
+ else
68
+ @value
69
+ end
69
70
  end
70
71
 
71
- def validate
72
- if !@value || @value.empty?
73
- if @attribute[:must]
74
- @error = "必須項目です。"
72
+ def normalize(val)
73
+ return val
74
+ end
75
+
76
+ def validate(val)
77
+ if !val || val.to_s.empty?
78
+ if @attribute[:required] == "true"
79
+ @error = "required"
75
80
  return @error
76
81
  end
77
82
  end
@@ -83,120 +88,271 @@ module Ezframe
83
88
  end
84
89
 
85
90
  def no_view?
86
- return (@attribute[:hidden] && !@attribute[:force])
91
+ return (@attribute[:hidden] || @attribute[:no_view]) && !@attribute[:force]
92
+ end
93
+
94
+ # 複数のinputを持っているか?
95
+ def multi_inputs?
96
+ nil
97
+ end
98
+
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
110
+ end
111
+
112
+ def make_error_box(name)
113
+ Ht.div(id: "error-box-#{name}", class: %w[error-box hide], child: "")
87
114
  end
88
115
  end
89
116
 
90
117
  class TextType < TypeBase
91
- def normalize
92
- return unless @value
93
- @value = @value.to_s
94
- @value.gsub!(/ /, " ")
95
- @value.gsub!(/\s+/, " ")
96
- @value.strip!
118
+ def normalize(val)
119
+ return nil unless val
120
+ val = val.dup.to_s
121
+ val.gsub!(/ /, " ")
122
+ # val.gsub!(/\s+/, " ")
123
+ val.strip!
124
+ return val
97
125
  end
98
126
 
99
- def value=(v)
100
- super(v)
101
- normalize
127
+ def value=(val)
128
+ @value = normalize(val)
102
129
  end
103
130
 
104
131
  def form(opts = {})
105
132
  return nil if no_edit? && !opts[:force]
106
- h = { tag: "input", type: "text", name: @attribute[:key], key: @attribute[:key], label: @attribute[:label], value: @value || "" }
107
- h[:size] = @attribute[:size] if @attribute[:size]
108
- h
133
+ key = self.key
134
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
135
+ h = Ht.input(type: "text", name: key, label: @attribute[:label], value: @value || "")
136
+ h[:class] = @attribute[:class] if @attribute[:class]
137
+ h[:after] = make_error_box(key)
138
+ return h
109
139
  end
110
140
 
111
141
  def db_type
112
- "text"
142
+ return "text"
143
+ end
144
+ end
145
+
146
+ class TextareaType < TextType
147
+ def value=(val)
148
+ @value = normalize(val)
149
+ @value = val
150
+ end
151
+
152
+ def form(opts = {})
153
+ return nil if no_edit? && !opts[:force]
154
+ val = @value
155
+ key = self.key
156
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
157
+ h = Ht.textarea(name: key, label: @attribute[:label], child: val)
158
+ h[:class] = @attribute[:class] if @attribute[:class]
159
+ h[:after] = make_error_box(key)
160
+ return h
113
161
  end
114
162
  end
115
163
 
116
164
  class IntType < TextType
117
165
  def view(opts = {})
118
166
  return nil if no_view? && !opts[:force]
119
- return Util.add_comma(@value.to_i)
167
+ return nil unless @value
168
+ return nil if @attribute[:no_view_if_zero] && @value.to_i == 0
169
+ if @attribute[:view_format]
170
+ return use_view_format(@attribute[:view_format], @value)
171
+ else
172
+ if @attribute[:add_comma]
173
+ return @value.to_i.add_comma
174
+ else
175
+ return @value.to_s
176
+ end
177
+ end
178
+ end
179
+
180
+ def normalize(val)
181
+ if val.is_a?(String)
182
+ val = val.tr("0-9", "0-9").strip
183
+ end
184
+ return val
120
185
  end
121
186
 
122
187
  def value=(v)
188
+ if v.nil?
189
+ default = @attribute[:default]
190
+ if default
191
+ @value = default
192
+ else
193
+ @value = nil
194
+ end
195
+ return
196
+ end
197
+
123
198
  if v.nil?
124
199
  @value = nil
125
200
  return
126
201
  end
127
- if v.is_a?(String)
128
- v = v.tr("0-9", "0-9").strip
202
+ unless v.is_a?(Integer) || v.is_a?(String)
203
+ EzLog.debug("value must integer or string: key=#{self.key}, #{v}: class=#{v.class}")
204
+ return
129
205
  end
206
+ v = normalize(v)
130
207
  @value = v.to_i
131
208
  end
132
209
 
133
210
  def form(opts = {})
134
211
  return nil if no_edit? && !opts[:force]
135
- { tag: "input", type: "number", key: @attribute[:key], label: @attribute[:label], value: @value || "" }
212
+ key = self.key
213
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
214
+ h = Ht.input(type: "number", name: key, label: @attribute[:label], value: @value || "")
215
+ h[:class] = @attribute[:class] if @attribute[:class]
216
+ h[:after] = make_error_box(key)
217
+ return h
136
218
  end
137
219
 
138
- def db_type
139
- "int"
220
+ def validate(val)
221
+ return nil if !val || val.to_s.strip.empty?
222
+ unless /^\d+$/ =~ val.to_s
223
+ return :invalid_value
224
+ end
225
+ return nil
140
226
  end
141
227
 
142
-
228
+ def db_type
229
+ return "int"
230
+ end
143
231
  end
144
232
 
145
233
  class ForeignType < IntType
234
+ attr_accessor :db_data
235
+
236
+ def target_table
237
+ table = @attribute[:table]
238
+ return table if table
239
+ return self.key
240
+ end
241
+
146
242
  def view(opts = {})
147
243
  return nil if no_view? && !opts[:force]
148
- dataset = @parent.db.dataset[self.type.inner]
149
- data = dataset.get(id: @value)
150
- return data[@attribute[:view]]
244
+ colkey = @attribute[:view_column]
245
+ if @value && colkey
246
+ data_h = DB::Cache[target_table.to_sym]
247
+ data = data_h[@value.to_i]
248
+ return nil unless data
249
+ return data[colkey.to_sym]
250
+ end
251
+ return nil
151
252
  end
152
253
 
153
- def form
154
- return nil
254
+ def form(opts = {})
255
+ return nil if no_edit? && !opts[:force]
256
+ view_key = @attribute[:menu_column] || @attribute[:view_column]
257
+ data_h = DB::Cache[target_table.to_sym]
258
+ menu_a = data_h.map do |id, data|
259
+ [ data[:id], data[view_key&.to_sym] ]
260
+ end
261
+ key = self.key
262
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
263
+ return Ht.select(name: key, class: %w[browser-default], item: menu_a, value: @value, after: make_error_box(key))
155
264
  end
156
- end
157
265
 
158
- class IdType < IntType
159
- def label
160
- return nil if no_view?
161
- return "ID"
266
+ def db_type
267
+ return "int"
268
+ end
269
+
270
+ def set_db_data
271
+ @db_data = {}
272
+ if @value
273
+ @db_data = DB::Cache[target_table.to_sym][@value]
274
+ end
162
275
  end
276
+ end
163
277
 
278
+ class IdType < IntType
164
279
  def form(opts = {})
165
280
  return nil
166
281
  end
167
282
  end
168
283
 
169
284
  class PasswordType < TextType
285
+ def initialize(attr = nil)
286
+ super(attr)
287
+ @attribute[:no_view] = true
288
+ end
289
+
290
+ def encrypt_value(val)
291
+ crypt = BCrypt::Password.create(val)
292
+ return crypt.to_s
293
+ end
294
+
295
+ def value_equal?(value_from_db, new_value)
296
+ crypt = BCrypt::Password.new(value_from_db)
297
+ return crypt == new_value
298
+ end
299
+
170
300
  def form(opts = {})
171
301
  return nil if no_edit? && !opts[:force]
172
- return { tag: "input", type: "password", label: @attribute[:label], value: @value || "" }
302
+ key = self.key
303
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
304
+ h = Ht.input(type: "password", name: key, label: @attribute[:label], value: "")
305
+ h[:class] = @attribute[:class] if @attribute[:class]
306
+ h[:after] = make_error_box(key)
307
+ return h
173
308
  end
174
309
 
175
310
  def db_value
176
- return value
311
+ crypt = BCrypt::Password.create(@value)
312
+ return crypt.to_s
177
313
  end
178
314
  end
179
315
 
180
316
  class SelectType < TypeBase
181
317
  def form(opts = {})
182
318
  return nil if no_edit? && !opts[:force]
183
- # puts "selectType: #{@attribute[:items].inspect}"
184
- return { tag: "select", key: @attribute[:key], label: @attribute[:label], items: @attribute[:items], value: @value }
319
+ @items ||= @attribute[:item]
320
+ h = Ht.select(class: %w[browser-default], name: self.key, label: @attribute[:label], item: @items, value: @value)
321
+ h[:class] = @attribute[:class] if @attribute[:class]
322
+ h[:after] = make_error_box(self.key)
323
+ return h
185
324
  end
186
325
 
187
326
  def db_type
188
327
  return "text"
189
328
  end
329
+
330
+ def view(opts = {})
331
+ return nil if no_view? && !opts[:force]
332
+ item = @attribute[:item]
333
+ # EzLog.debug("select.view: @value=#{@value}, #{@value.class}, item=#{item}, result=#{item[@value]}")
334
+ return nil unless @value
335
+ return item[@value.to_s.to_sym]
336
+ end
337
+
338
+ def validate(val)
339
+ return nil
340
+ end
190
341
  end
191
342
 
192
343
  class CheckboxType < TypeBase
193
344
  def form(opts = {})
194
345
  return nil if no_edit? && !opts[:force]
195
- return { tag: "checkbox", key: @attribute[:key], name: @attribute[:key], value: parent[:id].value, label: @attribute[:label] }
346
+ key = self.key
347
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
348
+ h = Ht.checkbox(name: key, value: parent[:id].value, label: @attribute[:label])
349
+ h[:class] = @attribute[:class] if @attribute[:class]
350
+ h[:after] = make_error_box(key)
351
+ return h
196
352
  end
197
353
 
198
354
  def db_type
199
- return "int"
355
+ return "text"
200
356
  end
201
357
  end
202
358
 
@@ -204,20 +360,23 @@ module Ezframe
204
360
  def form(opts = {})
205
361
  return nil if no_edit? && !opts[:force]
206
362
  h = super
363
+ return nil unless h
207
364
  if h
208
- # h[:type] = 'date'
365
+ # h[:type] = 'date'
209
366
  h[:type] = "text"
210
- h[:class] = "datepicker"
211
- h[:value] = value || ""
367
+ h[:value] = @value || ""
368
+ h[:class] = [ "datepicker" ]
369
+ h[:class].push(@attribute[:class]) if @attribute[:class]
212
370
  end
213
371
  return h
214
372
  end
215
373
 
216
374
  def db_type
217
- "date"
375
+ return "date"
218
376
  end
219
377
 
220
378
  def value
379
+ return nil if @value.nil? || (@value.is_a?(String) && @value.strip.empty?)
221
380
  if @value.is_a?(Date) || @value.is_a?(Time)
222
381
  return "%d-%02d-%02d" % [@value.year, @value.mon, @value.mday]
223
382
  end
@@ -226,7 +385,12 @@ module Ezframe
226
385
 
227
386
  def value=(v)
228
387
  if v.nil?
229
- @value = nil
388
+ default = @attribute[:default]
389
+ if default
390
+ @value = default
391
+ else
392
+ @value = nil
393
+ end
230
394
  return
231
395
  end
232
396
  if v.is_a?(String)
@@ -235,21 +399,24 @@ module Ezframe
235
399
  return
236
400
  end
237
401
  y, m, d = v.split(/[\-\/]/)
238
- # puts "date=#{v.inspect}"
239
402
  @value = Date.new(y.to_i, m.to_i, d.to_i)
240
403
  return
241
404
  end
242
405
  if v.is_a?(Date) || v.is_a?(Time)
243
406
  @value = v
244
407
  else
245
- mylog "[WARN] illegal value for date type: #{v.inspect}"
408
+ EzLog.info "[WARN] illegal value for date type: #{v.inspect}"
246
409
  end
247
410
  end
248
411
 
249
412
  def view(opts = {})
250
413
  return nil if no_view? && !opts[:force]
251
414
  if @value.is_a?(Time) || @value.is_a?(Date)
252
- return "#{@value.year}/#{@value.mon}/#{@value.mday}"
415
+ if @attribute[:view_format]
416
+ return use_view_format(@attribute[:view_format], @value)
417
+ else
418
+ return "%d-%02d-%02d" % [@value.year, @value.mon, @value.mday]
419
+ end
253
420
  else
254
421
  return @value
255
422
  end
@@ -257,31 +424,164 @@ module Ezframe
257
424
  end
258
425
 
259
426
  class TimeType < TextType
427
+ def db_value
428
+ return nil if @value.nil? || @value.strip.empty?
429
+ return @value
430
+ end
260
431
  end
261
432
 
262
- class DatetimeType < DateType
433
+ class DatetimeType < TextType
434
+ def initialize(attr = nil)
435
+ super(attr)
436
+ # @attribute[:class] = "datettimepicker" # for jquery datetimepicker
437
+ @attribute[:class] = "datetpicker"
438
+ end
439
+
440
+ def value=(v)
441
+ if v.nil?
442
+ default = @attribute[:default]
443
+ if default
444
+ @value = default
445
+ else
446
+ @value = nil
447
+ end
448
+ return
449
+ end
450
+ if v.is_a?(String)
451
+ if v.strip.empty?
452
+ @value = nil
453
+ return
454
+ end
455
+ begin
456
+ @value = DateTime.parse(v)
457
+ rescue => e
458
+ EzLog.warn("date format error: #{self.key}=#{v}:#{e}")
459
+ @value = nil
460
+ end
461
+ return
462
+ end
463
+ if v.is_a?(Date) || v.is_a?(Time) || v.is_a?(DateTime)
464
+ @value = v
465
+ else
466
+ EzLog.info "[WARN] illegal value for date type: #{v.inspect}"
467
+ end
468
+ end
469
+
470
+ def view(opts = {})
471
+ return nil if no_view? && !opts[:force]
472
+ if @value.is_a?(Time) || @value.is_a?(Date)
473
+ if @attribute[:view_format]
474
+ return use_view_format(@attribute[:view_format], @value)
475
+ else
476
+ return "%d/%02d/%02d %02d:%02d:%02d"%[@value.year, @value.mon, @value.mday, @value.hour, @value.min, @value.sec]
477
+ end
478
+ else
479
+ return @value
480
+ end
481
+ end
482
+
483
+ def form(opts = {})
484
+ # EzLog.debug("DatetimeType: key=#{self.key}, opts=#{opts}")
485
+ return nil if no_edit? && !opts[:force]
486
+ h = super
487
+ return nil unless h
488
+ if h
489
+ h[:type] = "text"
490
+ h[:value] = @value || ""
491
+ h[:class] = [ "datepicker" ]
492
+ h[:class].push(@attribute[:class]) if @attribute[:class]
493
+ end
494
+ return h
495
+ end
496
+
263
497
  def db_type
264
498
  "timestamp"
265
499
  end
500
+
501
+ def value
502
+ return nil if @value.nil? || (@value.is_a?(String) && @value.strip.empty?)
503
+ return @value if @value.is_a?(Date) || @value.is_a?(Time)
504
+ return DateTime.parse(@value) if @value.is_a?(String)
505
+ end
266
506
  end
267
507
 
268
- class BirthdayType < DateType
508
+ class BirthdayType < TextType
269
509
  def form(opts = {})
270
510
  return nil if no_edit? && !opts[:force]
271
- prefix = @attribute[:key]
272
511
  now = Time.now
273
512
  year_list = []
274
513
  110.times do |y|
275
514
  year = now.year - y - 10
276
- year_list.push [year, "#{year}(#{Japanese.convert_wareki(year)})"]
515
+ year_list.push [year, "#{year}(#{Japanese.convert_wareki(year)})"]
277
516
  end
278
- mon_list = (1..12).map { |m| [m, "#{m}月"] }
517
+ year_list.unshift([ 0, "(年)" ])
518
+
519
+ key = self.key
520
+ key ="#{key}#{opts[:key_suffix]}" if opts[:key_suffix]
521
+
522
+ year, mon, mday = parse_date(@value)
523
+ mon_list = (1..12).map { |m| [m, "#{m}"] }
279
524
  mon_list.unshift([0, "(月)"])
280
- mday_list = (1..31).map { |d| [d, "#{d}"] }
525
+ mday_list = (1..31).map { |d| [d, "#{d}"] }
281
526
  mday_list.unshift([0, "(日)"])
282
- return [Ht.select(name: "#{prefix}_year", items: year_list),
283
- Ht.select(name: "#{prefix}_mon", items: mon_list),
284
- Ht.select(name: "#{prefix}_mday", items: mday_list)]
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),
530
+ Ht.small("年")]),
531
+ Ht.select(name: "#{key}_mon", class: %w[browser-default multi_input], item: mon_list, value: mon, ezvalid: ezvalid),
532
+ Ht.small("月"),
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)])
536
+ end
537
+
538
+ def view(opts = {})
539
+ return nil if no_view? && !opts[:force]
540
+ return nil unless @value
541
+ year, mon, mday = parse_date(@value)
542
+ year_s = if year.to_i == 0 then "?" else "%d" % [year]; end
543
+ mon_s = if mon.to_i == 0 then "?" else "%2d" % [mon]; end
544
+ mday_s = if mday.to_i == 0 then "?" else "%2d" % [mday]; end
545
+ return "#{year_s}<small>年</small>#{mon_s}<small>月</small>#{mday_s}<small>日</small>"
546
+ end
547
+
548
+ def parse_date(date)
549
+ if date && date =~ /(\d+)\-(\d+)\-(\d+)/
550
+ return [ $1.to_i,$2.to_i,$3.to_i ]
551
+ end
552
+ return nil
553
+ end
554
+
555
+ def multi_inputs?
556
+ true
557
+ end
558
+
559
+ def form_to_value(form, target_key: nil)
560
+ key = target_key || self.key
561
+ y, m, d = form["#{key}_year".to_sym], form["#{key}_mon".to_sym], form["#{key}_mday".to_sym]
562
+ return "%d-%02d-%02d"%[y.to_i, m.to_i, d.to_i]
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
285
585
  end
286
586
  end
287
587
 
@@ -289,63 +589,103 @@ module Ezframe
289
589
  def form(opts = {})
290
590
  return nil if no_edit? && !opts[:force]
291
591
  h = super
292
- h[:type] = "email" if h
592
+ return nil unless h
593
+ h[:type] = "email"
594
+ h[:class] = @attribute[:class] if @attribute[:class]
293
595
  return h
294
596
  end
295
597
 
296
- def normalize
297
- return unless @value
298
- @value = NKF.nkf('-w -Z4', @value)
598
+ def normalize(val)
599
+ return nil unless val
600
+ return NKF.nkf('-w -Z4', val)
299
601
  end
300
602
 
301
- def validate
302
- super
603
+ def validate(val)
604
+ super(val)
303
605
  return @error if @error
304
- if email_format?
305
- @error = "形式が正しくありません"
606
+ return nil if !val || val.strip.empty?
607
+ unless email_format?(val)
608
+ @error = :invalid_value
306
609
  return @error
307
610
  end
308
611
  return nil
309
612
  end
310
613
 
311
- def email_format?
312
- return nil unless @value
313
- return @value =~ /^[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
614
+ def email_format?(val)
615
+ return val.to_s =~ /^[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
314
616
  end
315
617
  end
316
618
 
317
619
  class TelType < TextType
318
- def validate
319
- super
620
+ def normalize(val)
621
+ return nil unless val
622
+ val = super(val)
623
+ val = val.tr("0-9", "0-9")
624
+ # val = val.gsub(/\D+/, "")
625
+ return val
626
+ end
627
+
628
+ def validate(val)
629
+ super(val)
320
630
  return @error if @error
321
- unless /^0\d{9,10}$/ =~ @value
322
- @error = "形式が正しくありません"
631
+ return nil if !val || val.strip.empty?
632
+ unless /^0\d{9,10}$/ =~ val.to_s
633
+ @error = :invalid_value
323
634
  return @error
324
635
  end
636
+ return nil
325
637
  end
326
638
  end
327
639
 
640
+ class UrlType < TextType
641
+ end
642
+
328
643
  class JpnameType < TextType
329
644
  end
330
645
 
331
- class JpnameKanaType < TextType
332
- def normalize
333
- return unless @value
334
- super
335
- @value.tr!("ァ-ン", "ぁ-ん")
646
+ class KatakanaType < TextType
647
+ def normalize(val)
648
+ val = super(val)
649
+ return val.tr("ァ-ン", "ぁ-ん")
336
650
  end
337
651
 
338
- def validation
339
- unless /^[ぁ-ん ]+$/ =~ @value
340
- "ひらがなのみで入力してください。"
652
+ def validate(val)
653
+ super(val)
654
+ return @error if @error
655
+ return nil if !val || val.strip.empty?
656
+ unless /^[ぁ-ん ]+$/ =~ val.to_s
657
+ @error = :hiragana_only
658
+ return @error
659
+ end
660
+ return nil
661
+ end
662
+ end
663
+
664
+ class KatakanaType < TextType
665
+ def normalize(val)
666
+ return nil unless val
667
+ val = super(val)
668
+ return val.tr("ぁ-ん", "ァ-ン")
669
+ end
670
+
671
+ def validate(val)
672
+ super(val)
673
+ return @error if @error
674
+ return nil if !val || val.strip.empty?
675
+ unless /^[ァ-ン ]+$/ =~ val
676
+ @error = :katakana_only
677
+ return @error
341
678
  end
679
+ return nil
342
680
  end
343
681
  end
344
682
 
345
683
  class PrefectureType < SelectType
346
- def initialize(attr)
684
+ attr_accessor :pref_h
685
+
686
+ def initialize(attr = nil)
347
687
  super(attr)
348
- @pref_a = %w[選択してください 北海道 青森県 岩手県 宮城県 秋田県 山形県 福島県
688
+ @pref_a = %w[() 北海道 青森県 岩手県 宮城県 秋田県 山形県 福島県
349
689
  茨城県 栃木県 群馬県 埼玉県 千葉県 東京都 神奈川県
350
690
  新潟県 富山県 石川県 福井県 山梨県 長野県 岐阜県 静岡県 愛知県
351
691
  三重県 滋賀県 京都府 大阪府 兵庫県 奈良県 和歌山県
@@ -359,11 +699,13 @@ module Ezframe
359
699
  def form(opts = {})
360
700
  return nil if no_edit? && !opts[:force]
361
701
  h = super
362
- h[:items] = @pref_h
702
+ return nil unless h
703
+ h[:item] = @pref_h
363
704
  return h
364
705
  end
365
706
 
366
- def view
707
+ def view(opts = {})
708
+ return nil if no_view? && !opts[:force]
367
709
  return @pref_h[@value.to_i]
368
710
  end
369
711
  end
@@ -376,8 +718,23 @@ module Ezframe
376
718
  return @value.to_s.gsub(/(\d{3})(\d{4})/) { "#{$1}-#{$2}" }
377
719
  end
378
720
 
379
- def db_type
380
- return "text"
721
+ def normalize(val)
722
+ val = super(val)
723
+ return nil if !val || val.strip.empty?
724
+ val = val.tr("0-9", "0-9")
725
+ return val
726
+ end
727
+
728
+ def validate(val)
729
+ super(val)
730
+ return @error if @error
731
+ return nil if !val || val.to_s.strip.empty?
732
+
733
+ unless /^\d{7}$/ =~ val.to_s
734
+ @error = :invalid_value
735
+ return @error
736
+ end
737
+ return nil
381
738
  end
382
739
  end
383
740
  end