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.
- checksums.yaml +4 -4
- data/asset/html/index.html +1 -0
- data/asset/js/ezframe.js +49 -20
- data/exe/check_column_yml +64 -0
- data/exe/create_table +7 -4
- data/exe/dbmigrate +65 -14
- data/ezframe.gemspec +10 -11
- data/lib/ezframe.rb +2 -1
- data/lib/ezframe/auth.rb +33 -28
- data/lib/ezframe/column_set.rb +261 -97
- data/lib/ezframe/column_type.rb +207 -63
- data/lib/ezframe/config.rb +20 -3
- data/lib/ezframe/controller.rb +19 -16
- data/lib/ezframe/database.rb +162 -50
- data/lib/ezframe/editor.rb +7 -7
- data/lib/ezframe/ht.rb +21 -16
- data/lib/ezframe/html.rb +20 -19
- data/lib/ezframe/japanese_utils.rb +10 -0
- data/lib/ezframe/jquery-ui.rb +29 -0
- data/lib/ezframe/loader.rb +4 -4
- data/lib/ezframe/logger.rb +39 -0
- data/lib/ezframe/materialize.rb +5 -8
- data/lib/ezframe/message.rb +1 -1
- data/lib/ezframe/page_base.rb +27 -18
- data/lib/ezframe/route.rb +26 -28
- data/lib/ezframe/template.rb +2 -2
- data/lib/ezframe/util.rb +4 -6
- data/lib/ezframe/version.rb +1 -1
- metadata +32 -44
- data/asset/js/materialize.min.js +0 -6
- data/asset/js/mymaterialize.js +0 -38
- data/lib/ezframe/model.rb +0 -52
data/lib/ezframe/config.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
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
|
-
|
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
|
data/lib/ezframe/controller.rb
CHANGED
@@ -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.
|
9
|
-
|
6
|
+
Config.init
|
7
|
+
ColumnSets.init
|
8
|
+
DB.init
|
10
9
|
Message.init
|
11
|
-
Auth.
|
10
|
+
Auth.init if Config[:auth]
|
12
11
|
end
|
13
12
|
|
14
13
|
def exec(request, response)
|
15
14
|
@request = request
|
16
|
-
|
17
|
-
@request.env["model"] = model
|
15
|
+
page_instance, method, url_params, class_opts = Route::choose(request)
|
18
16
|
|
19
|
-
|
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
|
-
|
28
|
-
|
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
|
-
#
|
35
|
-
|
36
|
-
|
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
|
-
#
|
46
|
+
# Logger.debug("Controller.exec: response.body=#{response.body}")
|
44
47
|
end
|
45
48
|
|
46
49
|
def file_not_found(response)
|
data/lib/ezframe/database.rb
CHANGED
@@ -2,61 +2,173 @@
|
|
2
2
|
require "logger"
|
3
3
|
|
4
4
|
module Ezframe
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
data/lib/ezframe/editor.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
#
|
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.
|
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.
|
168
|
+
Ht.span([Ht.small(col.label), col.form(force: true)])
|
169
169
|
end
|
170
170
|
|
171
171
|
# エラーページの表示
|
data/lib/ezframe/ht.rb
CHANGED
@@ -3,17 +3,18 @@ module Ezframe
|
|
3
3
|
module Ht
|
4
4
|
class << self
|
5
5
|
# メソッド名の名前のタグのhthashを生成
|
6
|
-
def wrap_tag(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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 =
|
14
|
+
h = ht_h.dup
|
14
15
|
end
|
15
16
|
else
|
16
|
-
|
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, :
|
34
|
-
alias_method :hr, :
|
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, :
|
56
|
+
alias_method :img, :single_tag
|
49
57
|
alias_method :a, :wrap_tag
|
50
58
|
alias_method :form, :wrap_tag
|
51
|
-
alias_method :input, :
|
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)
|