ezframe 0.1.1 → 0.2.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.
@@ -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)