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/column_set.rb
CHANGED
@@ -2,54 +2,191 @@
|
|
2
2
|
|
3
3
|
module Ezframe
|
4
4
|
class ColumnSets
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class << self
|
6
|
+
def init(dir = nil)
|
7
|
+
dir ||= "./column"
|
8
|
+
unless @colset_h
|
9
|
+
@colset_h = {}
|
10
|
+
load_files(dir)
|
11
|
+
end
|
12
|
+
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
def load_files(dir)
|
15
|
+
Dir["#{dir}/*.yml"].each do |filename|
|
16
|
+
load_one_file(filename)
|
17
|
+
end
|
14
18
|
end
|
15
|
-
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
#begin
|
20
|
+
def load_one_file(filename)
|
21
|
+
colset_name = $1 if filename =~ /(\w+).ya?ml$/
|
20
22
|
yaml = YAML.load_file(filename)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
if yaml.length == 0
|
24
|
+
Logger.error("[ERROR] columns file is empty: #{filename}")
|
25
|
+
return
|
26
|
+
end
|
27
|
+
column_info = yaml.recursively_symbolize_keys
|
28
|
+
# puts "load_one_file: filename=#{filename} column_info=#{column_info.inspect}"
|
29
|
+
add(colset_name, column_info)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add(colset_name, columns)
|
33
|
+
@colset_h[colset_name.to_sym] = cs = ColumnSet.new(parent: self, name: colset_name, columns: columns)
|
34
|
+
cs.set(columns)
|
35
|
+
return cs
|
36
|
+
end
|
37
|
+
|
38
|
+
def clone
|
39
|
+
@colset_h.deep_dup
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_key?(key)
|
43
|
+
return nil unless key
|
44
|
+
return @colset_h[key.to_sym]
|
45
|
+
end
|
46
|
+
|
47
|
+
def get(colset_name)
|
48
|
+
return nil unless colset_name
|
49
|
+
return @colset_h[colset_name.to_sym].deep_dup
|
50
|
+
end
|
51
|
+
|
52
|
+
def refer(colset_name)
|
53
|
+
return nil unless colset_name
|
54
|
+
return @colset_h[colset_name.to_sym]
|
55
|
+
end
|
56
|
+
|
57
|
+
def [](colset_name)
|
58
|
+
return get(colset_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
def each
|
62
|
+
@colset_h.each { |k, v| yield(k, v) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def inspect
|
66
|
+
@colset_h.each do |name, colset|
|
67
|
+
"[#{name}]:#{colset.inspect}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_tables
|
72
|
+
self.each do |table_name, column_set|
|
73
|
+
begin
|
74
|
+
create_one_table(table_name, column_set)
|
75
|
+
rescue => e
|
76
|
+
Logger.error("create_tables: #{e.inspect}\n#{$@.inspect}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_one_table(table_name, column_set)
|
82
|
+
col_h = column_set.get_hash(:db_type)
|
83
|
+
Logger.info "create_one_table: col_h=#{col_h.inspect}"
|
84
|
+
DB.create_table(table_name, col_h)
|
85
|
+
end
|
86
|
+
|
87
|
+
# foreignから生成したテーブル連結情報を返す
|
88
|
+
def full_join_structure(colset_id)
|
89
|
+
struct = { tables: [colset_id] }
|
90
|
+
colset = @colset_h[colset_id.to_sym]
|
91
|
+
colset_keys = colset.keys
|
92
|
+
struct[:column_list] = colset_keys.map { |k| "#{colset_id}.#{k}" }
|
93
|
+
join_cond_h = {}
|
94
|
+
colset_keys.each do |key|
|
95
|
+
column = colset[key]
|
96
|
+
if column.type.to_s == "foreign"
|
97
|
+
# 連結するテーブル名をtable: で指定する。
|
98
|
+
foreign_table = column.attribute[:table]
|
99
|
+
# 指定されてなければ、キーの名称をテーブル名とする
|
100
|
+
# そのテーブルが定義されてなければ、エラーとしてログに残す。
|
101
|
+
unless foreign_table
|
102
|
+
if @colset_h[key]
|
103
|
+
foreign_table = key
|
104
|
+
else
|
105
|
+
Logger.error "There is no related table: #{key}"
|
106
|
+
next
|
107
|
+
end
|
108
|
+
end
|
109
|
+
raise "no table: key=#{key}" unless foreign_table
|
110
|
+
foreign_column = column.attribute[:column]&.to_sym || :id
|
111
|
+
foreign_table = foreign_table.to_sym
|
112
|
+
next if struct[:tables].include?(foreign_table)
|
113
|
+
# join_cond_h["#{colset_id}.#{key}"] = "#{colset_id}.#{key} = #{foreign_table}.#{foreign_column}"
|
114
|
+
join_cond_h[foreign_table] = "#{colset_id}.#{key} = #{foreign_table}.#{foreign_column}"
|
115
|
+
struct[:tables].push(foreign_table)
|
116
|
+
struct[:column_list] += ColumnSets.refer(foreign_table).keys.map {|k| "#{foreign_table}.#{k}" }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
struct[:join_condition] = join_cond_h
|
120
|
+
return struct
|
121
|
+
end
|
122
|
+
|
123
|
+
def join_complex_column
|
124
|
+
|
27
125
|
end
|
28
|
-
column_info = yaml.recursively_symbolize_keys
|
29
|
-
# puts "load_one_file: filename=#{filename} column_info=#{column_info.inspect}"
|
30
|
-
add(table_name, column_info)
|
31
126
|
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# ColumnSetを複数組み合わせて扱う
|
130
|
+
class ColumnSetCollection
|
131
|
+
attr_accessor :colset_list
|
32
132
|
|
33
|
-
def
|
34
|
-
@
|
35
|
-
|
133
|
+
def initialize(default_table=nil)
|
134
|
+
@colset_h = {}
|
135
|
+
@default_table = default_table
|
36
136
|
end
|
37
137
|
|
38
|
-
def
|
39
|
-
|
138
|
+
def values=(data)
|
139
|
+
@colset_h.each {|key, colset| colset.clear }
|
140
|
+
set_values(data)
|
40
141
|
end
|
41
142
|
|
42
|
-
def
|
43
|
-
|
143
|
+
def set_values(data)
|
144
|
+
data.each do |key, value|
|
145
|
+
if key.to_s.index(".")
|
146
|
+
table_key, col_key = key.to_s.split(".")
|
147
|
+
colset = @colset_h[table_key.to_sym]
|
148
|
+
unless colset
|
149
|
+
@colset_h[table_key.to_sym] = colset = ColumnSets[table_key]
|
150
|
+
end
|
151
|
+
elsif @default_table
|
152
|
+
col_key = key
|
153
|
+
colset = @colset_h[@default_table.to_sym]
|
154
|
+
unless colset
|
155
|
+
@colset_h[table_key.to_sym] = colset = ColumnSets[@default_table]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
colset[col_key].value = value
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def get(colset_key, col_key=nil)
|
163
|
+
if col_key.nil?
|
164
|
+
if colset_key.to_s.index(".")
|
165
|
+
colset_key, col_key = colset_key.to_s.split(".")
|
166
|
+
elsif @default_table
|
167
|
+
colset_key, col_key = @default_table, colset_key
|
168
|
+
else
|
169
|
+
Logger.error "ColumnSetCollection.get: illegal arguments: #{colset_key}, #{col_key}"
|
170
|
+
return nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
colset = @colset_h[colset_key.to_sym]
|
174
|
+
return nil unless colset
|
175
|
+
# Logger.debug("Collection.get: colset_key=#{colset_key}, col_key=#{col_key}, value=#{colset[col_key].value}")
|
176
|
+
return colset[col_key]
|
177
|
+
end
|
178
|
+
|
179
|
+
def [](k)
|
180
|
+
return get(k)
|
44
181
|
end
|
45
182
|
end
|
46
183
|
|
47
184
|
class ColumnSet
|
48
185
|
attr_accessor :name, :parent, :edit_keys, :view_keys
|
49
186
|
|
50
|
-
def initialize(parent
|
187
|
+
def initialize(parent: nil, name: nil, columns: nil)
|
51
188
|
@parent = parent
|
52
|
-
@name = name
|
189
|
+
@name = name
|
53
190
|
@columns ||= {}
|
54
191
|
set(columns) if columns
|
55
192
|
end
|
@@ -66,9 +203,9 @@ module Ezframe
|
|
66
203
|
|
67
204
|
# 配列を初期化する
|
68
205
|
def set(attr_a)
|
69
|
-
@columns[:id] = IdType.new(key: "id", label: "ID",
|
70
|
-
attr_a.each do |
|
71
|
-
attr =
|
206
|
+
@columns[:id] = IdType.new(key: "id", label: "ID", hidden: true)
|
207
|
+
attr_a.each do |attribute|
|
208
|
+
attr = attribute.clone
|
72
209
|
col_key = attr[:key]
|
73
210
|
raise "no column key: #{attr.inspect}" unless col_key
|
74
211
|
klass = TypeBase.get_class(attr[:type])
|
@@ -78,16 +215,14 @@ module Ezframe
|
|
78
215
|
@columns[col_key.to_sym] = klass.new(attr)
|
79
216
|
end
|
80
217
|
end
|
81
|
-
@columns[:created_at] = DatetimeType.new(type: "datetime", key: "created_at", label: "生成日時",
|
82
|
-
@columns[:updated_at] = DatetimeType.new(type: "datetime", key: "updated_at", label: "更新日時",
|
83
|
-
|
84
|
-
@columns.values.each {|col| col.parent = self }
|
218
|
+
@columns[:created_at] = DatetimeType.new(type: "datetime", key: "created_at", label: "生成日時", hidden: true)
|
219
|
+
@columns[:updated_at] = DatetimeType.new(type: "datetime", key: "updated_at", label: "更新日時", hidden: true)
|
220
|
+
@columns.values.each { |col| col.parent = self }
|
85
221
|
return @columns
|
86
222
|
end
|
87
223
|
|
88
224
|
def dataset
|
89
|
-
|
90
|
-
return @parent.model.db.dataset(@name)
|
225
|
+
return DB.dataset(@name)
|
91
226
|
end
|
92
227
|
|
93
228
|
def set_from_db(id)
|
@@ -97,19 +232,15 @@ module Ezframe
|
|
97
232
|
return data
|
98
233
|
end
|
99
234
|
|
100
|
-
#
|
101
|
-
def create
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
dataset.where(id: id.value).update(col_h)
|
110
|
-
else
|
111
|
-
return dataset.insert(col_h)
|
112
|
-
end
|
235
|
+
# データベースに新規に値を登録する
|
236
|
+
def create(value_h)
|
237
|
+
self.set_values(value_h)
|
238
|
+
db_value_h = self.get_hash(:db_value)
|
239
|
+
Logger.debug("column_set.create: #{db_value_h}")
|
240
|
+
db_value_h.delete(:id)
|
241
|
+
db_value_h[:updated_at] = Time.now
|
242
|
+
db_value_h[:created_at] = Time.now
|
243
|
+
return dataset.insert(db_value_h)
|
113
244
|
end
|
114
245
|
|
115
246
|
# データベース上の値の更新
|
@@ -125,15 +256,18 @@ module Ezframe
|
|
125
256
|
end
|
126
257
|
prev_value = column.value
|
127
258
|
column.value = new_value
|
128
|
-
if
|
259
|
+
if column.respond_to?("value_equal?")
|
260
|
+
unless column.value_equal?(prev_value, column.value)
|
261
|
+
updated_values[colkey] = column.set_for_db(value)
|
262
|
+
end
|
263
|
+
elsif prev_value != column.value
|
129
264
|
updated_values[colkey] = column.value
|
130
265
|
end
|
131
266
|
end
|
132
|
-
mylog "column_set.updated_values = #{updated_values.inspect}"
|
133
267
|
if updated_values.length > 0
|
134
268
|
updated_values[:updated_at] = Time.now
|
135
|
-
puts dataset.where(id: id).update_sql(updated_values)
|
136
|
-
dataset.where(id: id).update(updated_values)
|
269
|
+
# puts dataset.where(id: id).update_sql(updated_values)
|
270
|
+
dataset.where(id: id).update(updated_values)
|
137
271
|
end
|
138
272
|
end
|
139
273
|
|
@@ -142,50 +276,69 @@ module Ezframe
|
|
142
276
|
set_values(value_h)
|
143
277
|
end
|
144
278
|
|
279
|
+
# 各カラムに値を格納する
|
145
280
|
def set_values(value_h)
|
146
281
|
return unless value_h
|
147
|
-
|
148
|
-
next if
|
149
|
-
|
150
|
-
next unless
|
151
|
-
|
282
|
+
@columns.keys.each do |key|
|
283
|
+
next if key.nil? || key.to_s.empty?
|
284
|
+
column = @columns[key.to_sym]
|
285
|
+
next unless column
|
286
|
+
if column.respond_to?(:form_to_value) && !value_h.has_key?(key)
|
287
|
+
val = column.form_to_value(value_h)
|
288
|
+
else
|
289
|
+
val = value_h[key]
|
290
|
+
end
|
291
|
+
column.value = val
|
152
292
|
end
|
293
|
+
return self
|
153
294
|
end
|
154
295
|
|
155
|
-
|
296
|
+
# 各カラムのバリデーション
|
297
|
+
# 戻り値は[ 正規化した値, エラーシンボル(Messageのキーと紐づく) ]を値として、
|
298
|
+
# カラムキーをキーとするハッシュ
|
299
|
+
def validate(value_h)
|
300
|
+
return {} unless value_h
|
156
301
|
clear_error
|
157
|
-
|
158
|
-
@columns.values.each do |col|
|
159
|
-
|
160
|
-
|
302
|
+
result_h = {}
|
303
|
+
@columns.values.each do |col|
|
304
|
+
res = []
|
305
|
+
if col.respond_to?(:form_to_value) && !value_h.has_key?(col.key)
|
306
|
+
orig_val = col.form_to_value(value_h)
|
307
|
+
else
|
308
|
+
orig_val = value_h[col.key]
|
309
|
+
end
|
310
|
+
new_val = col.normalize(orig_val)
|
311
|
+
res[0] = new_val if orig_val != new_val
|
312
|
+
res[1] = col.validate(new_val)
|
313
|
+
result_h[col.key] = res if res[0] || res[1]
|
161
314
|
end
|
162
|
-
return
|
315
|
+
return result_h
|
163
316
|
end
|
164
317
|
|
165
318
|
def clear_error
|
166
|
-
@columns.values.each {|col| col.error = nil }
|
319
|
+
@columns.values.each { |col| col.error = nil }
|
167
320
|
end
|
168
321
|
|
169
322
|
def values
|
170
|
-
@columns.map {|key, col| col.value}
|
171
|
-
end
|
323
|
+
@columns.map { |key, col| col.value }
|
324
|
+
end
|
172
325
|
|
173
326
|
def each
|
174
|
-
@columns.values.each {|column| yield(column) }
|
327
|
+
@columns.values.each { |column| yield(column) }
|
175
328
|
end
|
176
329
|
|
177
330
|
def map
|
178
|
-
@columns.values.map {|column| yield(column) }
|
331
|
+
@columns.values.map { |column| yield(column) }
|
179
332
|
end
|
180
333
|
|
181
334
|
def get_matrix(method_a)
|
182
335
|
return @columns.map do |_key, col|
|
183
|
-
|
184
|
-
|
336
|
+
method_a.map { |method| col.send(method) }
|
337
|
+
end
|
185
338
|
end
|
186
339
|
|
187
340
|
def get_hash(method)
|
188
|
-
res_h = {}
|
341
|
+
res_h = {}
|
189
342
|
@columns.map do |key, col|
|
190
343
|
res_h[key.to_sym] = col.send(method)
|
191
344
|
end
|
@@ -195,41 +348,52 @@ module Ezframe
|
|
195
348
|
def [](col_key)
|
196
349
|
return @columns[col_key.to_sym]
|
197
350
|
end
|
198
|
-
|
351
|
+
|
199
352
|
def form
|
200
353
|
if @edit_keys
|
201
|
-
return @edit_keys.map do |key|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
354
|
+
return @edit_keys.map do |key|
|
355
|
+
col = @columns[key.to_sym]
|
356
|
+
unless col
|
357
|
+
Logger.info "[ERROR] @edit_keys has unknown column:name=#{@name}:key=#{key}"
|
358
|
+
next
|
359
|
+
end
|
360
|
+
col.form
|
361
|
+
end
|
209
362
|
else
|
210
|
-
return
|
211
|
-
end
|
363
|
+
return @columns.values.map { |coltype| coltype.form }
|
364
|
+
end
|
212
365
|
end
|
213
366
|
|
214
367
|
def view
|
215
368
|
if @view_keys
|
216
|
-
return @view_keys.map do |key|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
369
|
+
return @view_keys.map do |key|
|
370
|
+
col = @columns[key.to_sym]
|
371
|
+
unless col
|
372
|
+
Logger.info "[ERROR] @view_keys has unknown column:name=#{@name}:key=#{key}"
|
373
|
+
next
|
374
|
+
end
|
375
|
+
col.view
|
376
|
+
end
|
224
377
|
else
|
225
|
-
return
|
378
|
+
return @columns.values.map { |coltype| coltype.view }
|
226
379
|
end
|
227
380
|
end
|
228
381
|
|
382
|
+
def get_full_join(opts = {})
|
383
|
+
struct = ColumnSets.full_join_structure(self.name)
|
384
|
+
return DB.get_join_table(struct, opts)
|
385
|
+
end
|
386
|
+
|
229
387
|
def hidden_form
|
230
388
|
return @columns.map do |colkey, coltype|
|
231
|
-
|
232
|
-
|
389
|
+
{ tag: "input", id: colkey, name: colkey, type: "hidden", value: coltype.value }
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def inpsect
|
394
|
+
@columns.map do |colkey, coltype|
|
395
|
+
"#{colkey}=#{coltype.value}"
|
396
|
+
end.join(" ")
|
233
397
|
end
|
234
398
|
end
|
235
399
|
end
|