ezframe 0.0.4 → 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.
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
@@ -4,17 +4,16 @@ module Ezframe
4
4
  class Materialize
5
5
  class << self
6
6
  def into_html_header
7
-
8
- css_a = Config[:extra_css_list].map {|file| "<link href=\"#{file}\" rel=\"stylesheet\">\n" }
9
- js_a = Config[:extra_js_list].map {|file| "<script src=\"#{file}\"></script>\n" }
7
+ css_a = Config[:extra_css_list]&.map {|file| "<link href=\"#{file}\" rel=\"stylesheet\">\n" }
8
+ js_a = Config[:extra_js_list]&.map {|file| "<script src=\"#{file}\"></script>\n" }
10
9
 
11
10
  css_files = Dir["./asset/css/*.css"]||[]
12
- css_a += css_files.map do |file|
11
+ css_a += css_files.sort.map do |file|
13
12
  file.gsub!("./asset", "")
14
13
  "<link href=\"#{file}\" rel=\"stylesheet\">\n"
15
14
  end
16
15
  js_files = Dir["./asset/js/*.js"]||[]
17
- js_a += js_files.map do |file|
16
+ js_a += js_files.sort.map do |file|
18
17
  file.gsub!("./asset", "")
19
18
  "<script src=\"#{file}\"></script>\n"
20
19
  end
@@ -27,19 +26,16 @@ module Ezframe
27
26
 
28
27
  def convert(ht_h)
29
28
  return nil unless ht_h
30
- return ht_h if (ht_h.kind_of?(Hash) && ht_h[:final])
29
+ return ht_h if (ht_h.is_a?(Hash) && ht_h[:final])
31
30
  new_h = ht_h.clone
32
- if ht_h.kind_of?(Array)
31
+ if ht_h.is_a?(Array)
33
32
  new_h = ht_h.map { |v| convert(v) }
34
- elsif ht_h.kind_of?(Hash)
33
+ elsif ht_h.is_a?(Hash)
35
34
  unless ht_h[:tag]
36
- mylog("convert: no tag: #{ht_h.inspect}")
35
+ EzLog.info("convert: no tag: #{ht_h.inspect}")
37
36
  return nil
38
37
  end
39
38
  case ht_h[:tag].to_sym
40
- # when :input, :select
41
- # new_h = input(ht_h) if "hidden" != ht_h[:type]
42
- # return new_h
43
39
  when :checkbox
44
40
  return checkbox(ht_h)
45
41
  when :radio
@@ -58,8 +54,8 @@ module Ezframe
58
54
 
59
55
  def icon(ht_h)
60
56
  new_h = ht_h.clone
61
- mylog "[warn] no name attribute for icon ht_h: #{ht_h.inspect}" unless new_h[:name]
62
- new_h.add_class("material-icons")
57
+ EzLog.info "[warn] no name attribute for icon ht_h: #{ht_h.inspect}" unless new_h[:name]
58
+ new_h.add_class(%w[material-icons align-icon])
63
59
  new_h.update({ tag: "i", child: ht_h[:name] })
64
60
  new_h.delete(:name)
65
61
  return new_h
@@ -0,0 +1,46 @@
1
+ module Ezframe
2
+ class Message
3
+ class << self
4
+ def init
5
+ load_yaml_files
6
+ end
7
+
8
+ def load_yaml_files(dir = "./message")
9
+ unless @catalog
10
+ @catalog = {}
11
+ Dir["#{dir}/*.yml"].each do |file|
12
+ load_one_file(file)
13
+ end
14
+ end
15
+ end
16
+
17
+ def load_one_file(file)
18
+ begin
19
+ yaml = YAML.load(File.open(file), symbolize_names: true)
20
+ rescue
21
+ EzLog.info("YAML load error: #{file}")
22
+ return
23
+ end
24
+ if /([a-z]{2})\.yml$/ =~ file
25
+ lang = $1
26
+ @catalog[lang.to_sym] = yaml # .recursively_symbolize_keys
27
+ end
28
+ end
29
+
30
+ def languages
31
+ return @catalog.keys
32
+ end
33
+
34
+ def get(key, lang = nil)
35
+ lang = languages[0] unless lang
36
+ messages = @catalog[lang]
37
+ return messages[key.to_sym] if messages
38
+ return nil
39
+ end
40
+
41
+ def [](key)
42
+ return get(key)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -2,106 +2,94 @@
2
2
 
3
3
  require "json"
4
4
  require "uri"
5
-
6
5
  require_relative "util"
7
6
 
8
7
  module Ezframe
9
8
  class PageBase
10
- class << self
11
- def decide_route(path_info)
12
- default_class = Config[:default_page_class]||"App"
13
- default_method = Config[:default_page_method]||"default"
14
- path_parts = path_info.split('/').drop(1)
15
- case path_parts.length
16
- when 0
17
- [get_class(default_class), default_method]
18
- when 1
19
- filename = path_parts[0]
20
- if filename.index(".")
21
- return nil
22
- end
23
- klass = get_class(path_parts)
24
- if klass
25
- return [klass, default_method]
26
- else
27
- return [get_class(default_class), path_parts[0]]
28
- end
29
- else
30
- klass = get_class(path_parts)
31
- if klass
32
- [klass, default_method]
33
- else
34
- method = path_parts.pop
35
- klass = get_class(path_parts)
36
- [klass, method]
37
- end
38
- end
39
- end
9
+ attr_accessor :request
40
10
 
41
- def get_class(keys)
42
- keys = [keys] if keys.is_a?(String)
43
- klass = (%w[Ezframe] + keys.map { |k| k.to_camel }).join("::")
44
- mylog "get_class: #{klass}"
45
- if Object.const_defined?(klass)
46
- return Object.const_get(klass)
47
- end
48
- return nil
49
- end
11
+ def initialize(request = nil)
12
+ @class_snake = class_to_snake(self.class)
13
+ # puts "class_snake = #{@class_snake}"
14
+ set_request(request) if request
15
+ init_vars
50
16
  end
51
17
 
52
- attr_accessor :auth
18
+ def init_vars
19
+ end
20
+
21
+ # Rackのrequestを代入し、関連するインスタンス変数を定義
22
+ def set_request(request)
23
+ @request = request
24
+ @column_set = ColumnSets.get(@class_snake)
25
+ @dataset = DB.dataset(@class_snake)
26
+ EzLog.debug "column_set is not defined: #{@class_snake}" unless @column_set
27
+ @params = parse_query_string(request.env["QUERY_STRING"])
28
+ @params.update(request.params)
29
+ # EzLog.info "set_request: params=#{@params.inspect}" if @params.length > 0
30
+ # @id, @key = @params[:id], @params[:key]
31
+ @env = @request.env
32
+ @session = @env["rack.session"]
53
33
 
54
- def initialize(request = nil, model = nil)
55
- @model = model if model
56
- if request
57
- @request = request
58
- @params = parse_query_string(request.env["QUERY_STRING"])
59
- @params.update(request.params)
60
- mylog "params=#{@params.inspect}" if @params.length > 0
61
- @id, @key = @params[:id], @params[:key]
62
- @env = @request.env
63
- @session = @env["rack.session"]
64
- mylog "session = #{@session.inspect}"
65
- if request.post?
66
- parse_json_body
67
- mylog "json=#{@json.inspect}"
34
+ if %w[POST PUT].include?(request.request_method)
35
+ body = @request.body.read
36
+ if request.content_type.index("json")
37
+ @parsed_body = parse_json_body(body)
38
+ else
39
+ @parsed_body = parse_query_string(body)
68
40
  end
41
+ # EzLog.info "parsed_body=#{@parsed_body.inspect}"
42
+ @event = @parsed_body[:ezevent] || {}
43
+ @form = @event[:form]
69
44
  end
70
- @auth = nil
71
45
  end
72
46
 
73
- def parse_query_string(str)
74
- query_a = URI::decode_www_form(str)
75
- res_h = {}
76
- query_a.map { |a| res_h[a[0].to_sym] = a[1] }
77
- res_h
47
+ # routeから基本URLを生成
48
+ def make_base_url(id = nil)
49
+ path = Route::get_path(@class_snake)
50
+ params = @request.env["url_params"] || {}
51
+ # EzLog.info "make_base_url: params=#{params}"
52
+ # params[@class_snake.to_sym] = id
53
+ path_s = path.map do |pa|
54
+ if pa == @class_snake.to_sym && id
55
+ "#{pa}/#{id}"
56
+ elsif params[pa.to_sym]
57
+ "#{pa}/#{params[pa.to_sym]}"
58
+ else
59
+ pa
60
+ end
61
+ end.join("/")
62
+ # EzLog.info "path_s=#{path_s}"
63
+ return "/#{path_s}"
78
64
  end
79
65
 
80
- def common_page(opts = {})
66
+ def show_base_template(opts = {})
81
67
  args = {
82
68
  title: opts[:title],
83
69
  body: opts[:body],
84
70
  into_html_header: Materialize.into_html_header,
85
71
  into_bottom_of_body: Materialize.into_bottom_of_body,
86
72
  }
87
- Template.fill("template/base.html", args)
73
+ Template.fill_from_file("template/base.html", args)
88
74
  end
89
75
 
90
- def parse_json_body
91
- body = @request.body.read
76
+ def parse_json_body(body)
92
77
  return {} if !body || body.length==0
93
78
  begin
94
- @json = JSON.parse(body)
79
+ json = JSON.parse(body, symbolize_names: true)
95
80
  rescue => e
96
- mylog "ERROR: #{e.class}:#{e.message}\n#{e.backtrace}"
81
+ EzLog.info "ERROR: #{e.class}:#{e.message}\n#{e.backtrace}"
97
82
  return nil
98
83
  end
99
- @json = @json.recursively_symbolize_keys if @json.is_a?(Hash) || @json.is_a?(Array)
100
- return @json
84
+ return json
85
+ end
86
+
87
+ def session
88
+ return @request.env['rack.session']
101
89
  end
102
90
 
103
91
  def warden
104
- @request.env["warden"]
92
+ return @request.env["warden"]
105
93
  end
106
94
 
107
95
  def login?
@@ -109,7 +97,7 @@ module Ezframe
109
97
  end
110
98
 
111
99
  def user
112
- warden.user
100
+ return warden.user
113
101
  end
114
102
  end
115
103
  end
@@ -0,0 +1,126 @@
1
+ module Ezframe
2
+ class Route
3
+ class << self
4
+ def choose(request, route_h = nil)
5
+ path_parts = request.path_info.split("/").drop(1)
6
+ route_h ||= Config[:route].deep_dup
7
+ unless route_h
8
+ raise "Config[:route] is not defined. It should be defined in config/route.yml"
9
+ end
10
+ # puts "config=#{Config[:route]}, route_h=#{route_h}"
11
+ args = {}
12
+ opts = {}
13
+ class_a = []
14
+ # p path_parts
15
+ if path_parts.empty?
16
+ root_conf = route_h[:/]
17
+ # p root_conf
18
+ if root_conf
19
+ klass = get_class(root_conf[:class])
20
+ return [ klass.new, make_method_name("default", request.request_method) ]
21
+ end
22
+ return [ 404 ]
23
+ end
24
+ # URLを解析して、クラスの決定とIDの取得を行う
25
+ while path_parts.length > 0
26
+ part = path_parts.shift
27
+ # break if part.empty?
28
+ # EzLog.info "part=#{part}, route_h=#{route_h.inspect}"
29
+ if route_h.has_key?(part.to_sym)
30
+ # EzLog.info "has_route: #{part}"
31
+ class_a.push(part)
32
+ if path_parts[0].to_i > 0
33
+ args[part.to_sym] = val = path_parts.shift
34
+ # EzLog.info "value: part=#{part}, val=#{val}"
35
+ end
36
+ route_h = route_h[part.to_sym]
37
+ break if route_h.nil?
38
+ opts = {}
39
+ route_h.keys.compact.each do |rkey|
40
+ if rkey =~ /option_(\w+)/
41
+ opt_key = $1
42
+ opts[opt_key.to_sym] = route_h[rkey]
43
+ end
44
+ end
45
+ else
46
+ # routeに無ければ、メソッドを探す
47
+ # EzLog.info "no_route: #{part}"
48
+ klass = get_class(class_a[-1])
49
+ return [ 404 ] unless klass
50
+ instance = klass.new
51
+ method_name = make_method_name(part, request.request_method)
52
+ if instance.respond_to?(method_name)
53
+ return [instance, method_name, args, opts]
54
+ else
55
+ EzLog.info "undefined method: #{klass}.#{method_name}: full path=#{request.path_info}"
56
+ end
57
+ end
58
+ end
59
+ # 最後にメソッド名が無い場合はpublic_default_#{method}を実行。
60
+ #puts "class_a=#{class_a}"
61
+ klass = get_class(class_a[-1])
62
+ return [404] unless klass
63
+ if path_parts.length > 0
64
+ part = path_parts.shift
65
+ else
66
+ part = "default"
67
+ end
68
+ method_name = make_method_name(part, request.request_method)
69
+ #EzLog.info "method_name=#{method_name}"
70
+ instance = klass.new
71
+ if instance.respond_to?(method_name)
72
+ return [instance, method_name, args, opts]
73
+ end
74
+ return [ 404 ]
75
+ end
76
+
77
+ # ページクラスの階層を辿る
78
+ def get_path(class_snake, route_h = nil)
79
+ route_h = Config[:route] unless route_h
80
+ # EzLog.info "get_path: route_h=#{route_h}"
81
+ @get_path_found_it = nil
82
+ route =_scan_route(class_snake, route_h.deep_dup)
83
+ return route.reverse if route
84
+ return nil
85
+ end
86
+
87
+ # targetに対応する名称のクラスまでの経路を返す
88
+ def _scan_route(target, route_h)
89
+ if route_h.keys.include?(target.to_sym)
90
+ @get_path_found_it = true
91
+ return [ target ]
92
+ else
93
+ route_h.each do |k, v|
94
+ next if k.to_s =~ /^option_/
95
+ if v.is_a?(Hash)
96
+ a = _scan_route(target, v)
97
+ if @get_path_found_it
98
+ a.push(k)
99
+ return a
100
+ end
101
+ end
102
+ end
103
+ end
104
+ return nil
105
+ end
106
+
107
+ def make_method_name(base_name, method = "get")
108
+ return ["public", base_name, method.downcase].join("_")
109
+ end
110
+
111
+ def get_class(keys)
112
+ # EzLog.info "get_class: #{keys.inspect}"
113
+ return nil unless keys
114
+ keys = [ keys ] if keys.is_a?(String)
115
+ klass = (%w[Ezframe] + keys.map { |k| k.to_s.to_camel }).join("::")
116
+ # EzLog.info "get_class: #{klass}"
117
+ if Object.const_defined?(klass)
118
+ return Object.const_get(klass)
119
+ else
120
+ raise "get_class: undefined class: #{klass}"
121
+ end
122
+ return nil
123
+ end
124
+ end
125
+ end
126
+ end
@@ -2,14 +2,25 @@
2
2
 
3
3
  module Ezframe
4
4
  class Server
5
- def self.call(env)
5
+ def initialize
6
+ Controller.init
7
+ end
8
+
9
+ def call(env)
6
10
  req = Rack::Request.new(env)
7
11
  res = Rack::Response.new
8
- Boot.exec(req, res)
9
- if res.body.empty?
10
- raise "no body in response"
12
+ begin
13
+ Controller.exec(req, res)
14
+ rescue => e
15
+ EzLog.error("Controller.exec: exception: #{e.message}:\n#{e.backtrace}")
16
+ res.status = 500
17
+ res.headers["Content-Type"] = "text/plain"
18
+ res.body = [ "Internal server error" ]
11
19
  end
12
- res.finish
20
+ # if res.body.empty?
21
+ # raise "no body in response"
22
+ # end
23
+ return res.finish
13
24
  end
14
25
  end
15
26
  end
@@ -0,0 +1,22 @@
1
+ require_relative "editor_common"
2
+ require_relative "single_page_kit"
3
+
4
+ module Ezframe
5
+ # ページ遷移無しでデータを編集する仕組み
6
+ class SinglePageEditor < PageBase
7
+ include EditorCommon
8
+ include PageKit::Default
9
+ include PageKit::Index
10
+ include PageKit::Edit
11
+ include PageKit::Detail
12
+ include PageKit::Delete
13
+
14
+ def init_vars
15
+ super
16
+ @sort_key = :id
17
+ @event = @parsed_body[:ezevent] if @parsed_body
18
+ @dom_id = { create: "create-area", edit: "edit-area", index: "index-area", detail: "detail-area"}
19
+ # @show_delete_button = nil
20
+ end
21
+ end
22
+ end