ezframe 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,14 +3,27 @@ module Ezframe
3
3
  class << self
4
4
  attr_accessor :value_h
5
5
 
6
+ def init(dir = "./config")
7
+ load_files(dir)
8
+ end
9
+
6
10
  def load_files(dir)
7
11
  unless @value_h
8
- Dir["#{dir}/*.yml"].each do |file|
9
- load_one_file(file)
12
+ load_dir(dir)
13
+ rack_env = ENV['RACK_ENV']
14
+ env_dir = "#{dir}/#{rack_env}"
15
+ if rack_env && File.directory?(env_dir)
16
+ load_dir(env_dir)
10
17
  end
11
18
  end
12
19
  end
13
20
 
21
+ def load_dir(dir)
22
+ Dir["#{dir}/*.yml"].each do |file|
23
+ load_one_file(file)
24
+ end
25
+ end
26
+
14
27
  def load_one_file(filename)
15
28
  instr = File.open(filename, &:read)
16
29
  if instr.index("\#{")
@@ -19,7 +32,7 @@ module Ezframe
19
32
  begin
20
33
  yaml = YAML.load(instr)
21
34
  rescue
22
- mylog("YAML load error: #{filename}")
35
+ Logger.info("YAML load error: #{filename}")
23
36
  return
24
37
  end
25
38
  @value_h ||={}
@@ -35,6 +48,10 @@ module Ezframe
35
48
  @value_h[k]=v
36
49
  end
37
50
 
51
+ def delete(k)
52
+ @value_h.delete(k) if @value_h[k]
53
+ end
54
+
38
55
  def inspect
39
56
  @value_h.inspect
40
57
  end
@@ -1,46 +1,49 @@
1
1
  # frozen_string_literal: true
2
- require "oj"
3
-
4
2
  module Ezframe
5
3
  class Controller
6
4
  class << self
7
5
  def init
8
- Config.load_files("./config")
9
- Model.init
6
+ Config.init
7
+ ColumnSets.init
8
+ DB.init
10
9
  Message.init
11
- Auth.init_warden if defined?(Warden)
10
+ Auth.init if Config[:auth]
12
11
  end
13
12
 
14
13
  def exec(request, response)
15
14
  @request = request
16
- model = Model.get_clone
17
- @request.env["model"] = model
15
+ page_instance, method, url_params, class_opts = Route::choose(request)
18
16
 
19
- mylog("exec: path=#{request.path_info} params=#{request.params}")
20
- page_instance, method, url_params = Route::choose(request)
21
- mylog "page: #{page_instance.class}, method=#{method}, url_params=#{url_params}"
17
+ Logger.debug("Controller.exec: path=#{request.path_info}, params=#{request.params}, class=#{page_instance.class}, method=#{method}, url_params=#{url_params}, class_opts=#{class_opts}")
22
18
  if !page_instance || page_instance == 404
23
19
  file_not_found(response)
24
20
  return
25
21
  end
26
22
  @request.env["url_params"] = url_params
27
- warden.authenticate! if page_instance.auth
28
- mylog "rack.session.keys=#{request.env['rack.session'].keys}"
23
+ opt_auth = class_opts[:auth]
24
+ @session = @request.env['rack.session']
25
+ if !@session[:user] && Config[:auth] && (!opt_auth || opt_auth != "disable")
26
+ Logger.debug("authenticate!")
27
+ warden.authenticate!
28
+ Logger.info "Controller.exec: warden.options = #{@request.env['warden.options']}"
29
+ end
30
+ # session["in_controller"] = "set in controller"
31
+ Logger.debug "rack.session.keys=#{@session.keys}" if @session
29
32
  page_instance.set_request(@request)
30
33
  body = page_instance.send(method)
31
34
 
32
35
  # 戻り値によるレスポンス生成
33
36
  if body.is_a?(Hash) || body.is_a?(Array)
34
- # puts "Controller: body = #{body}"
35
- response.body = [ JSON.generate(body) ]
36
- # response.body = [ Oj.dump(body) ]
37
+ # Logger.debug("Controller: body = #{body}")
38
+ json = JSON.generate(body)
39
+ response.body = [ json ]
37
40
  response['Content-Type'] = 'application/json; charset=utf-8'
38
41
  else
39
42
  response.body = [ body ]
40
43
  response['Content-Type'] = 'text/html; charset=utf-8'
41
44
  end
42
45
  response.status = 200
43
- # puts response.body
46
+ # Logger.debug("Controller.exec: response.body=#{response.body}")
44
47
  end
45
48
 
46
49
  def file_not_found(response)
@@ -2,61 +2,173 @@
2
2
  require "logger"
3
3
 
4
4
  module Ezframe
5
- class Database
6
- attr_accessor :sequel
7
-
8
- def initialize(dbfile = nil)
9
- @dbfile = dbfile
10
- connect
11
- end
12
-
13
- def connect
14
- @dbfile ||= ENV["EZFRAME_DB"] || Config[:database] || "sqlite://db/devel.sqlite"
15
- # puts "Database.connect: dbfile=#{@dbfile}"
16
- @sequel = Sequel.connect(@dbfile, loggers: [Logger.new($stdout)])
17
- end
18
-
19
- def exec(sql)
20
- @sequel.run(sql)
21
- end
22
-
23
- def dataset(table_name)
24
- @sequel[table_name.to_sym]
25
- end
26
-
27
- def create_table(table_name, dbtype_h)
28
- %w[id created_at updated_at].each do |key|
29
- dbtype_h.delete(key.to_sym)
30
- end
31
- # puts "create_table: #{table_name}"
32
- if @dbfile.index("postgres")
33
- @sequel.create_table(table_name) do
34
- primary_key :id, identity: true
35
- dbtype_h.each do |key, dbtype|
36
- column(key, dbtype)
5
+ class DB
6
+ class << self
7
+ attr_accessor :sequel, :pool
8
+
9
+ def init(dbfile = nil, opts = {})
10
+ @dbfile = dbfile || ENV["EZFRAME_DB"] || Config[:database]
11
+ if Config[:use_connection_pool] || opts[:use_connection_pool]
12
+ @pool = Sequel::ConnectionPool(max_connections: 10) do
13
+ Sequel.connect(@dbfile, loggers: [Logger])
37
14
  end
38
- column(:created_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
39
- column(:updated_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
40
- end
41
- else
42
- @sequel.create_table(table_name) do
43
- primary_key :id, auto_increment: true
44
- dbtype_h.each do |key, dbtype|
45
- column(key, dbtype)
15
+ else
16
+ connect(@dbfile)
17
+ end
18
+ end
19
+
20
+ def connect(dbfile = nil)
21
+ dbfile ||= @dbfile
22
+ @sequel = Sequel.connect(dbfile, loggers: [Logger])
23
+ return @sequel
24
+ end
25
+
26
+ def disconnect
27
+ @sequel.disconnect
28
+ end
29
+
30
+ def get_conn
31
+ if @pool
32
+ @pool.hold {|conn| return conn }
33
+ else
34
+ @sequel
35
+ end
36
+ end
37
+
38
+ def exec(sql, first: nil)
39
+ conn = get_conn
40
+ if first
41
+ return conn[sql].first
42
+ else
43
+ return conn[sql].all
44
+ end
45
+ end
46
+
47
+ def run(sql)
48
+ conn = get_conn
49
+ conn.run(sql)
50
+ end
51
+
52
+ def dataset(table_name)
53
+ @sequel[table_name.to_sym]
54
+ end
55
+
56
+ class JointHash < Hash
57
+ def initialize(default_table, values = {})
58
+ @default_table = default_table
59
+ self.update(values)
60
+ end
61
+
62
+ def []=(key, value)
63
+ super(key.to_s, value)
64
+ end
65
+
66
+ def [](key)
67
+ key = key.to_s
68
+ return fetch(key) if has_key?(key)
69
+ alt_key = "#{@default_table}.#{key}"
70
+ return fetch(alt_key) if has_key?(alt_key)
71
+ return nil
72
+ end
73
+ end
74
+
75
+ # テーブルを連結して、全てのデータを返す。
76
+ def get_join_table(structure, opts = {})
77
+ col_h = {}
78
+ reverse_col_h = {}
79
+ query_a = []
80
+ table_a = []
81
+ prefix="_x_"
82
+ structure[:column_list].each_with_index do |k, i|
83
+ key = "#{prefix}#{i+1}"
84
+ col_h[k.to_sym] = key.to_sym
85
+ reverse_col_h[key.to_sym] = k
86
+ query_a.push "#{k} AS #{key}"
87
+ end
88
+ tables = structure[:tables].clone
89
+ join_cond = structure[:join_condition]
90
+ tb = tables.shift
91
+ table_part = [ tb ]
92
+ tables.each do |table|
93
+ cond = join_cond[table.to_sym]
94
+ if cond
95
+ table_part.push " LEFT JOIN #{table} ON #{cond}"
96
+ else
97
+ table_part.push " LEFT JOIN #{table} ON #{tb}.#{table} = #{table}.id"
98
+ end
99
+ end
100
+ sql = "SELECT #{query_a.join(', ')} FROM #{table_part.join(' ')}"
101
+ sql += " WHERE #{opts[:where]}" if opts[:where]
102
+ sql += " ORDER BY #{opts[:order]}" if opts[:order]
103
+ sql += " LIMIT #{opts[:limit]}" if opts[:limit]
104
+ data_a = self.exec(sql)
105
+ res_a = []
106
+ data_a.each do |data|
107
+ new_data = JointHash.new(tb)
108
+ data.each do |k, v|
109
+ orig_key = reverse_col_h[k.to_sym]
110
+ next unless orig_key
111
+ new_data[orig_key] = v
46
112
  end
47
- column(:created_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
48
- column(:updated_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
113
+ res_a.push(new_data)
49
114
  end
115
+ return res_a
116
+ end
117
+
118
+ # テーブル生成
119
+ def create_table(table_name, dbtype_h)
120
+ %w[id created_at updated_at].each do |key|
121
+ dbtype_h.delete(key.to_sym)
122
+ end
123
+ # puts "create_table: #{table_name}"
124
+ if @dbfile.index("postgres")
125
+ @sequel.create_table(table_name) do
126
+ primary_key :id, identity: true
127
+ dbtype_h.each do |key, dbtype|
128
+ column(key, dbtype)
129
+ end
130
+ column(:created_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
131
+ column(:updated_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
132
+ end
133
+ else
134
+ @sequel.create_table(table_name) do
135
+ primary_key :id, auto_increment: true
136
+ dbtype_h.each do |key, dbtype|
137
+ column(key, dbtype)
138
+ end
139
+ column(:created_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
140
+ column(:updated_at, :timestamp, default: Sequel::CURRENT_TIMESTAMP)
141
+ end
142
+ end
143
+ end
144
+
145
+ def insert(table_name, val_h)
146
+ dataset(table_name).insert(val_h)
147
+ end
148
+
149
+ def update(dataset, val_h)
150
+ val_h.update({ updated_at: Time.now() })
151
+ dataset.update(val_h)
50
152
  end
51
- end
52
-
53
- def insert(table_name, val_h)
54
- dataset(table_name).insert(val_h)
55
153
  end
56
154
 
57
- def update(dataset, val_h)
58
- val_h.update({ updated_at: Time.now() })
59
- dataset.update(val_h)
60
- end
155
+ class Cache
156
+ class << self
157
+
158
+ def [](table)
159
+ @store ||= {}
160
+ dataset = DB.dataset(table.to_sym)
161
+ # Logger.debug("DB::Cache: #{table}")
162
+ unless @store[table.to_sym]
163
+ data_a = dataset.all
164
+ h = {}
165
+ data_a.each {|data| h[data[:id]] = data }
166
+ @store[table.to_sym] = h
167
+ end
168
+ # Logger.debug(@store[table.to_sym])
169
+ return @store[table.to_sym]
170
+ end
171
+ end
172
+ end
61
173
  end
62
174
  end
@@ -84,7 +84,7 @@ module Ezframe
84
84
  table = []
85
85
  matrix = @column_set.map do |column|
86
86
  form = column.form
87
- table.push Ht.p([ Ht.small_text(column.label), form ]) if form
87
+ table.push Ht.p([ Ht.small(column.label), form ]) if form
88
88
  end
89
89
  send_button = Ht.button(child: Message[:edit_finish_button_label], class: %w[btn], event: "on=click:url=#{make_base_url(@id)}/#{command}:with=form")
90
90
  table.push(send_button)
@@ -94,7 +94,7 @@ module Ezframe
94
94
  #--------------------------------------------------------------------------------------------------------
95
95
  # 検索
96
96
  def public_search_post
97
- mylog "public_search_post: #{@parsed_body.inspect}"
97
+ Logger.info "public_search_post: #{@parsed_body.inspect}"
98
98
  sch_keys = @search_keys || @column_set.keys
99
99
  word = @params["word"]
100
100
  pattern = "%#{word}%"
@@ -107,7 +107,7 @@ module Ezframe
107
107
 
108
108
  # 詳細表示
109
109
  def show_detail_page
110
- mylog "show_detail_page: #{@request.params.inspect}"
110
+ Logger.info "show_detail_page: #{@request.params.inspect}"
111
111
  id = get_id(@class_snake)
112
112
  unless @column_set.set_from_db(id)
113
113
  return show_message_page("no data", "data is not defined: #{id}")
@@ -128,7 +128,7 @@ module Ezframe
128
128
  edit_btn = edit_button(column)
129
129
  edit_btn[:event] = "on=click:branch=edit_column:key=#{column.key}" if edit_btn
130
130
  end
131
- table.push(Ht.p(class: %w[hover-button-box], child: [ Ht.small_text(column.label), column.view, edit_btn ].compact))
131
+ table.push(Ht.p(class: %w[hover-button-box], child: [ Ht.small(column.label), column.view, edit_btn ].compact))
132
132
  end
133
133
  unless @column_edit_mode
134
134
  edit_btn = Ht.button(class: %w[btn], child: [ Ht.icon("edit"), Message[:edit_button_label] ], event: "on=click:url=#{make_base_url(@id)}/edit")
@@ -146,7 +146,7 @@ module Ezframe
146
146
  class_name ||= @class_snake
147
147
  params = @request.env['url_params']
148
148
  return nil unless params
149
- # mylog "get_id: #{params.inspect}, #{class_name}"
149
+ # Logger.info "get_id: #{params.inspect}, #{class_name}"
150
150
  return params[class_name.to_sym]
151
151
  end
152
152
 
@@ -159,13 +159,13 @@ module Ezframe
159
159
  # ラベル付きで1カラムのviewを表示
160
160
  def show_label_view(key)
161
161
  col = @column_set[key]
162
- Ht.span([Ht.small_text(col.label), col.view(force: true)])
162
+ Ht.span([Ht.small(col.label), col.view(force: true)])
163
163
  end
164
164
 
165
165
  # ラベル付きで1カラムのformを表示
166
166
  def show_label_edit(key)
167
167
  col = @column_set[key]
168
- Ht.span([Ht.small_text(col.label), col.form(force: true)])
168
+ Ht.span([Ht.small(col.label), col.form(force: true)])
169
169
  end
170
170
 
171
171
  # エラーページの表示
@@ -3,17 +3,18 @@ module Ezframe
3
3
  module Ht
4
4
  class << self
5
5
  # メソッド名の名前のタグのhthashを生成
6
- def wrap_tag(opts = {})
7
- if opts.is_a?(String) || opts.is_a?(Array)
8
- h = { child: opts }
9
- elsif opts.is_a?(Hash)
10
- if opts[:tag] && !__callee__.to_s.index("wrap_tag")
11
- h = { child: opts }
6
+ def wrap_tag(ht_h = {})
7
+ return nil unless ht_h
8
+ if ht_h.is_a?(String) || ht_h.is_a?(Array)
9
+ h = { child: ht_h }
10
+ elsif ht_h.is_a?(Hash)
11
+ if ht_h[:tag] && !__callee__.to_s.index("wrap_tag")
12
+ h = { child: ht_h }
12
13
  else
13
- h = opts.dup
14
+ h = ht_h.dup
14
15
  end
15
16
  else
16
- mylog("wrap_tag: unknown type: #{opts.inspect}")
17
+ Logger.info("[WARN] wrap_tag: unknown type: #{ht_h.inspect}")
17
18
  return nil
18
19
  end
19
20
  h[:tag] ||= __callee__.to_s
@@ -21,6 +22,13 @@ module Ezframe
21
22
  return h
22
23
  end
23
24
 
25
+ def single_tag(ht_h = {})
26
+ ht_h[:tag] ||= __callee__.to_s
27
+ raise "no tag" if ht_h[:tag] == "wrap_tag"
28
+ raise "has child: #{ht_h.inspect}" if ht_h[:child]
29
+ return ht_h
30
+ end
31
+
24
32
  alias_method :script, :wrap_tag
25
33
 
26
34
  alias_method :h1, :wrap_tag
@@ -30,8 +38,8 @@ module Ezframe
30
38
  alias_method :h5, :wrap_tag
31
39
  alias_method :h6, :wrap_tag
32
40
  alias_method :p, :wrap_tag
33
- alias_method :br, :wrap_tag
34
- alias_method :hr, :wrap_tag
41
+ alias_method :br, :single_tag
42
+ alias_method :hr, :single_tag
35
43
  alias_method :div, :wrap_tag
36
44
  alias_method :span, :wrap_tag
37
45
  alias_method :i, :wrap_tag
@@ -45,10 +53,10 @@ module Ezframe
45
53
  alias_method :tr, :wrap_tag
46
54
  alias_method :th, :wrap_tag
47
55
  alias_method :td, :wrap_tag
48
- alias_method :img, :wrap_tag
56
+ alias_method :img, :single_tag
49
57
  alias_method :a, :wrap_tag
50
58
  alias_method :form, :wrap_tag
51
- alias_method :input, :wrap_tag
59
+ alias_method :input, :single_tag
52
60
  alias_method :select, :wrap_tag
53
61
  alias_method :textarea, :wrap_tag
54
62
  alias_method :label, :wrap_tag
@@ -58,6 +66,7 @@ module Ezframe
58
66
 
59
67
  alias_method :small, :wrap_tag
60
68
  alias_method :pre, :wrap_tag
69
+ alias_method :iframe, :wrap_tag
61
70
 
62
71
  alias_method :checkbox, :wrap_tag
63
72
  alias_method :radio, :wrap_tag
@@ -90,10 +99,6 @@ module Ezframe
90
99
  return child
91
100
  end
92
101
 
93
- def small_text(text)
94
- return small(class: %w[teal-text], child: text)
95
- end
96
-
97
102
  def search(ht_h, opts)
98
103
  @found ||= []
99
104
  if ht_h.is_a?(Hash)