ezframe 0.0.1 → 0.0.3

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +11 -4
  4. data/app_template/asset/image/favicon.ico +0 -0
  5. data/app_template/asset/js/ezframe.js +288 -0
  6. data/app_template/config/generic.yml +3 -0
  7. data/app_template/config/materialize.yml +5 -0
  8. data/{example/chat → app_template}/config.ru +2 -10
  9. data/app_template/pages/basic.rb +5 -0
  10. data/exe/create_table.rb +1 -0
  11. data/exe/setup.rb +15 -0
  12. data/ezframe.gemspec +3 -4
  13. data/lib/ezframe/auth.rb +15 -12
  14. data/lib/ezframe/column_set.rb +68 -28
  15. data/lib/ezframe/column_type.rb +231 -68
  16. data/lib/ezframe/config.rb +4 -0
  17. data/lib/ezframe/controller.rb +20 -10
  18. data/lib/ezframe/database.rb +10 -3
  19. data/lib/ezframe/ht.rb +167 -0
  20. data/lib/ezframe/html.rb +28 -4
  21. data/lib/ezframe/japanese_utils.rb +40 -0
  22. data/lib/ezframe/{pages.rb → loader.rb} +3 -0
  23. data/lib/ezframe/materialize.rb +55 -20
  24. data/lib/ezframe/model.rb +0 -2
  25. data/lib/ezframe/page_base.rb +18 -12
  26. data/lib/ezframe/page_kit.rb +12 -33
  27. data/lib/ezframe/template.rb +20 -15
  28. data/lib/ezframe/util.rb +5 -0
  29. data/lib/ezframe/version.rb +1 -1
  30. data/lib/ezframe.rb +5 -4
  31. metadata +27 -70
  32. data/example/auth/Gemfile +0 -8
  33. data/example/auth/asset/css/materialize.min.css +0 -13
  34. data/example/auth/asset/js/common.js +0 -200
  35. data/example/auth/asset/js/htmlgen.js +0 -79
  36. data/example/auth/columns/user.yml +0 -12
  37. data/example/auth/config/view_conf.yml +0 -3
  38. data/example/auth/config.ru +0 -26
  39. data/example/auth/pages/app.rb +0 -61
  40. data/example/auth/template/base.html +0 -12
  41. data/example/chat/Gemfile +0 -9
  42. data/example/chat/asset/css/materialize.min.css +0 -13
  43. data/example/chat/asset/js/common.js +0 -200
  44. data/example/chat/asset/js/htmlgen.js +0 -79
  45. data/example/chat/columns/belong.yml +0 -6
  46. data/example/chat/columns/channel.yml +0 -3
  47. data/example/chat/columns/talk.yml +0 -6
  48. data/example/chat/columns/user.yml +0 -12
  49. data/example/chat/config/view_conf.yml +0 -3
  50. data/example/chat/pages/app.rb +0 -59
  51. data/example/chat/template/base.html +0 -12
  52. data/example/todo/Gemfile +0 -8
  53. data/example/todo/asset/css/datatable.css +0 -54
  54. data/example/todo/asset/css/materialize.min.css +0 -13
  55. data/example/todo/asset/js/common.js +0 -135
  56. data/example/todo/asset/js/datatable.js +0 -1814
  57. data/example/todo/asset/js/htmlgen.js +0 -79
  58. data/example/todo/asset/js/init.js +0 -3
  59. data/example/todo/asset/js/materialize.min.js +0 -6
  60. data/example/todo/asset/js/mydatatable.js +0 -9
  61. data/example/todo/asset/js/mymaterialize.js +0 -22
  62. data/example/todo/columns/todo.yml +0 -9
  63. data/example/todo/config/view_conf.yml +0 -3
  64. data/example/todo/config.ru +0 -15
  65. data/example/todo/pages/app.rb +0 -93
  66. data/example/todo/template/base.html +0 -12
  67. data/exe/myrackup +0 -5
  68. data/lib/ezframe/hthash.rb +0 -116
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 872c21ee29e5590b12c895415e69d95c3d1c4f76dabfe1295ad100b3e2f05b9f
4
- data.tar.gz: 4b7e60705c6ea94ee56b67dd4343b04cc1c6eb4cadf96ce5f3b7c10fd1f05221
3
+ metadata.gz: 66c032e7ea5bbeaaccb2afb326e586b64566e2a55fcc4402abfd5629caf80418
4
+ data.tar.gz: 790b2060a76feccd9970dcd3c6cf452dbfb3b42834e3dbfbee7196f173b2b8f1
5
5
  SHA512:
6
- metadata.gz: bc4597ab89948f4e2eecd7da41c2cf065a7cd38bde8d42d4c1032624490d427bc68727762d79d2cd41e324fa976358224439c518fa41eb3dea5e0f05c1cadc99
7
- data.tar.gz: 3871153cd7e232392dd112ed165749c6a53ca3747a18de73e4e723b9114ddb49687f3d151e90a0c4e03fdb6671e98c61fa820d6d0fc255a19a5219931443664d
6
+ metadata.gz: b402c070b7bd0664709f8d12ea14e88ea29fba58e649d49b86394d1cff120ffae755eb2c255055709a31d41ec542f58535d171fa1e2a00e4c583918141e8d9b7
7
+ data.tar.gz: 6a5f44ba9417b892c77ad61ccb0316dbdf6d945aff93cfed1c2161ec173e44a7e2f6396b19a74e872b147d42ecd4a3d7adc167b57fc30974f18949b627858114
data/.gitignore CHANGED
@@ -10,3 +10,4 @@ db/*
10
10
  **/db/*
11
11
  pkg/
12
12
  *.old
13
+ *.gem
data/README.md CHANGED
@@ -1,18 +1,25 @@
1
1
  # ezframe
2
2
 
3
- ezframeは主にRubyで記述されたウェブフレームワークです。
4
- 最小の学習コストで、最大限の柔軟性を実現することを目指して開発しています。
3
+ ezframeは主にRubyで記述されたウェブフレームワークです。
4
+ 以下を目指して開発を進めています。
5
5
 
6
- ## 使い方
6
+ * Ruby言語でのプログラミングだけでリッチなGUIを持つウエブアプリを作れる。
7
+ * 最小の学習コストで、最大限の柔軟性を実現する。
8
+ * コードの再利用性を高める
9
+ * 他ライブラリーへの依存は極力少なくし、見通しの良さ
10
+
11
+ ## 基本的な使い方
7
12
 
8
13
  1. レポジトリーの取得
9
14
  ```sh
10
15
  git clone git@github.com:sakura-forest/ezframe.git
11
16
  cd ezframe
12
17
  bundle install --path vendor/bundle
18
+ bundle exec rackup
13
19
  ```
20
+
14
21
  2. columns/に、データ項目を記したyamlファイルを生成
15
- 例: vi columns/user.yml
22
+ 例: vi columns/address.yml
16
23
 
17
24
  ```yaml
18
25
  - key: name
@@ -0,0 +1,288 @@
1
+ function add_event(obj) {
2
+ var elems = obj.querySelectorAll('[event]')
3
+ if (elems) {
4
+ console.log("events=" + elems.length)
5
+ for (var i = 0; i < elems.length; i++) {
6
+ var elem = elems[i]
7
+ var event_s = elem.getAttribute("event")
8
+ // console.log(event_s)
9
+ var event = parse_event(event_s)
10
+ if (event.on == "load" && !elem.event_done) {
11
+ console.log("load: "+event_s)
12
+ execute_event(elem)
13
+ elem.event_done = 1
14
+ } else {
15
+ elem.addEventListener(event.on, function () {
16
+ execute_event(this)
17
+ })
18
+ }
19
+ }
20
+ }
21
+ register_switch_event(obj)
22
+ register_hover_button(obj)
23
+ // initialize_materialize()
24
+ // var elems = document.querySelectorAll('.dropdown-trigger')
25
+ // var instances = M.Dropdown.init(elems, {})
26
+ }
27
+
28
+ function parse_event(event) {
29
+ var ev = {}
30
+ var a = event.split(":")
31
+ for (var i = 0; i < a.length; i++) {
32
+ if (a[i].indexOf("=") > 0) {
33
+ var b = a[i].split("=")
34
+ var key = b[0]
35
+ var value = b[1]
36
+ if (value.indexOf(",") > 0) {
37
+ value = value.split(",")
38
+ }
39
+ var cur_value = ev[key]
40
+ if (cur_value) {
41
+ if (Array.isArray(cur_value)) {
42
+ cur_value.push(value)
43
+ } else {
44
+ ev[key] = [ev[key], value]
45
+ }
46
+ } else {
47
+ ev[key] = value
48
+ }
49
+ }
50
+ }
51
+ /*if (!ev.url) {
52
+ ev.url = location.pathname
53
+ }*/
54
+ return ev
55
+ }
56
+
57
+ function execute_event(obj) {
58
+ console.log("execute_event")
59
+ // console.dir(obj)
60
+ var event_s = obj.getAttribute("event")
61
+ var event = parse_event(event_s)
62
+ switch(event.branch) {
63
+ case "switch":
64
+ var a = event.between
65
+ for(var i = 0; i < a.length; i++) {
66
+ switch_hide(a[i])
67
+ }
68
+ return
69
+ case "set_global":
70
+ if (!window.ezframe) { window.ezframe = {} }
71
+ for(key in event) {
72
+ if ([ "branch", "on", "url" ].indexOf(key) >= 0) { continue }
73
+ window.ezframe[key] = event[key]
74
+ }
75
+ // console.log("set_global:" + JSON.stringify(window.ezframe))
76
+ return
77
+ case "redirect":
78
+ console.log("redirect:" + event.url)
79
+ location.href = event.url
80
+ return
81
+ }
82
+ with_attr(event, obj)
83
+ post_values(event, obj)
84
+ }
85
+
86
+ function with_attr(event, obj) {
87
+ if (!event.with) {
88
+ return null
89
+ }
90
+ var with_s = event.with
91
+ switch(event.with) {
92
+ case "form":
93
+ var node = obj
94
+ while (node && node.nodeName != 'FORM') {
95
+ node = node.parentNode
96
+ }
97
+ form = collect_form_values(node)
98
+ event.form = form
99
+ break;
100
+ case "input":
101
+ event.form = {}
102
+ event.form[obj.name] = obj.value
103
+ break;
104
+ }
105
+ }
106
+
107
+ function post_values(event, obj) {
108
+ var xhr = new XMLHttpRequest()
109
+ xhr.onreadystatechange = function () {
110
+ if (this.readyState == 4 && this.status == 200) {
111
+ var res = this.response
112
+ manage_response(res, event, obj)
113
+ }
114
+ }
115
+ if (!event.url) {
116
+ event.url = "/default"
117
+ }
118
+ console.log("post_values: url="+event.url+",event="+JSON.stringify(event))
119
+ xhr.open("POST", event.url, true)
120
+ xhr.setRequestHeader("Content-Type", "application/json")
121
+ xhr.responseType = 'json'
122
+ send_values = { event: event }
123
+ if (window.ezframe) {
124
+ send_values.global = window.ezframe
125
+ }
126
+ xhr.send(JSON.stringify(send_values))
127
+ }
128
+
129
+ function manage_response(res, event, obj) {
130
+ var elem
131
+ /* console.log("manage_response: res="+JSON.stringify(res)+", event=" + JSON.stringify(event) +
132
+ ", obj=" + JSON.stringify(obj))
133
+ */
134
+ if (!res) { return }
135
+ if (Array.isArray(res)) {
136
+ for(var i = 0; i < res.length; i++) {
137
+ exec_one_response(res[i])
138
+ }
139
+ } else {
140
+ exec_one_response(res)
141
+ }
142
+ }
143
+
144
+ function exec_one_response(res) {
145
+ if (res.inject) {
146
+ console.log("inject: " + res.inject)
147
+ elem = document.querySelector(res.inject)
148
+ if (elem) {
149
+ if (res.is_html) {
150
+ elem.innerHTML = res.body
151
+ } else {
152
+ elem.innerHTML = htmlgen(res.body)
153
+ }
154
+ add_event(elem)
155
+ } else {
156
+ console.log("inject: no such element: "+res.inject)
157
+ }
158
+ }
159
+ if (res.set_value) {
160
+ console.log("set_value: "+res.set_value+", value=", res.value)
161
+ elem = document.querySelector(res.set_value)
162
+ if (elem) {
163
+ if (res.set_value.indexOf("select") > 0) {
164
+ elem.selectedIndex = res.value
165
+ } else {
166
+ elem.value = res.value
167
+ }
168
+ } else {
169
+ console.log("set_value: no such element: "+res.set_value)
170
+ }
171
+ }
172
+ if (res.redirect) {
173
+ console.log("redirect:" + res.redirect)
174
+ location.href = res.redirect
175
+ return
176
+ }
177
+ if (res.scroll) {
178
+ scroll_to(res.scroll)
179
+ }
180
+ if (res.reset) {
181
+ elem = document.querySelector(res.reset)
182
+ if (event.reset == "form") {
183
+ while (node && node.nodeName != 'FORM') {
184
+ node = node.parentNode
185
+ }
186
+ node.reset();
187
+ }
188
+ }
189
+ }
190
+
191
+ function collect_form_values(obj) {
192
+ var res = {};
193
+ var inputs = Array.from(obj.querySelectorAll("input"));
194
+ var selects = Array.from(obj.querySelectorAll("select"));
195
+ var textareas = Array.from(obj.querySelectorAll("textarea"));
196
+ // console.dir(inputs)
197
+ inputs = inputs.concat(selects)
198
+ inputs = inputs.concat(textareas)
199
+ for (var i = 0; i < inputs.length; i++) {
200
+ var elem = inputs[i]
201
+ if (!elem.name) { continue }
202
+ console.log("name,value="+elem.name+","+elem.value)
203
+ if ((elem.type == "checkbox" || elem.type == "radio") && !elem.checked) {
204
+ continue
205
+ }
206
+ var cur_value = res[elem.name]
207
+ var elem_value = normalize(elem.value)
208
+ if (cur_value) {
209
+ if (Array.isArray(cur_value)) {
210
+ cur_value.push(elem_value)
211
+ } else {
212
+ res[elem.name] = [ cur_value, elem_value ]
213
+ }
214
+ } else {
215
+ res[elem.name] = elem_value
216
+ }
217
+ }
218
+ return res
219
+ }
220
+
221
+ function normalize(str) {
222
+ return str.replace(/^[\s| ]+|[\s| ]+$/g, '').trim()
223
+ }
224
+
225
+ function switch_hide(button) {
226
+ // console.log("switch_hide")
227
+ var node = button
228
+ while (node && !node.classList.contains('switch-box')) {
229
+ node = node.parentNode
230
+ }
231
+ var switch_box = node
232
+
233
+ var elems = switch_box.querySelectorAll(".switch-element")
234
+ for(var i = 0; i < elems.length; i++) {
235
+ var elem = elems[i]
236
+ var list = elem.classList
237
+ if (list.contains("hide")) {
238
+ elem.classList.remove("hide")
239
+ } else {
240
+ elem.classList.add("hide")
241
+ }
242
+ }
243
+ }
244
+
245
+ function register_switch_event(elem) {
246
+ var boxes = elem.querySelectorAll(".switch-box")
247
+ for(var i = 0; i < boxes.length; i++) {
248
+ var box = boxes[i]
249
+ var buttons = box.querySelectorAll(".switch-button")
250
+ for(var j = 0; j < buttons.length; j++) {
251
+ var button = buttons[j]
252
+ button.addEventListener('click', function() { switch_hide(this) })
253
+ }
254
+ }
255
+ }
256
+
257
+ function register_hover_button(obj) {
258
+ var elems = obj.querySelectorAll(".hover-button")
259
+ for(var i = 0; i < elems.length; i++) {
260
+ var node = elems[i]
261
+ while(node && node.classList.contains("hover-button-box") ) { node = node.parentNode }
262
+ var parent = elems[i].parentNode.parentNode
263
+ parent.addEventListener('mouseenter', function() {
264
+ var elem = this.querySelector(".hover-button")
265
+ elem.classList.remove("hide")
266
+ })
267
+ parent.addEventListener('mouseleave', function() {
268
+ var elem = this.querySelector(".hover-button")
269
+ elem.classList.add("hide")
270
+ })
271
+ }
272
+ }
273
+
274
+ function scroll_to(query) {
275
+ var element = document.querySelector(query)
276
+ if (element) {
277
+ element.getBoundingClientRect().top
278
+ var height = window.screenY - rect.top
279
+ console.log("scroll_to_form_top: " + height)
280
+ window.scroll({ top: height, behavior: "smooth" })
281
+ } else {
282
+ console.log("no such element: "+query)
283
+ }
284
+ }
285
+
286
+ document.addEventListener('DOMContentLoaded', function () {
287
+ add_event(document)
288
+ })
@@ -0,0 +1,3 @@
1
+ default_page_class: BasicPages
2
+ template_file: base.html
3
+ favicon: /image/favicon.ico
@@ -0,0 +1,5 @@
1
+ extra_js_list:
2
+ - https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js
3
+ extra_css_list:
4
+ - https://fonts.googleapis.com/icon?family=Material+Icons
5
+ - https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css
@@ -3,21 +3,13 @@
3
3
  require "logger"
4
4
  require "rack"
5
5
  require "rack-flash"
6
- require "warden"
6
+ require 'rack/session/redis'
7
7
 
8
8
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
9
9
  require "ezframe"
10
10
 
11
- use Warden::Manager do |manager|
12
- manager.default_strategies :mystrategy
13
- manager.failure_app = Proc.new do |env|
14
- ["401", { "Content-Type" => "text/html" }, [ Ezframe::App.new.public_login_page ]]
15
- end
16
- end
17
-
18
- use Rack::Session::Pool, secret: Digest::SHA256.hexdigest(rand.to_s)
11
+ use Rack::Session::Pool
19
12
  use Rack::Static, urls: ["/image", "/js", "/css"], root: "asset"
20
13
  use Rack::ShowExceptions
21
14
  use Rack::Flash, :accessorize => [:notice, :error]
22
-
23
15
  run Ezframe::Server
@@ -0,0 +1,5 @@
1
+ class BasicPages < Ezframe::PageBase
2
+ def public_default_page
3
+ return "<H1>Ezframe is working.</H1>"
4
+ end
5
+ end
data/exe/create_table.rb CHANGED
@@ -6,6 +6,7 @@ $:.push("lib")
6
6
  require 'ezframe'
7
7
  require 'sequel'
8
8
 
9
+ Ezframe::Config.load_files("config")
9
10
  Ezframe::Model.init
10
11
  model = Ezframe::Model.get_clone
11
12
  model.create_tables
data/exe/setup.rb ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ #coding: utf-8
3
+ =begin
4
+
5
+ アプリケーションテンプレートの生成
6
+
7
+ =end
8
+ require "fileutils"
9
+
10
+ target_dir = ARGV[0]
11
+
12
+ unless File.exist?(target_dir)
13
+ Dir.mkdir(target_dir)
14
+ end
15
+ FileUtils.cp_r("app_template", target_dir)
data/ezframe.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["KAMACHI Masayuki"]
10
10
  spec.email = ["kamachi@sakuraforest.co.jp"]
11
11
 
12
- spec.summary = %q{simple and easy-to-use web framework}
12
+ spec.summary = %q{simple and easy-to-use web framework by ruby language}
13
13
  spec.description = %q{easy web framework}
14
14
  spec.homepage = "https://github.com/sakura-forest/ezframe"
15
15
  spec.license = "MIT"
@@ -31,13 +31,12 @@ Gem::Specification.new do |spec|
31
31
  spec.require_paths = ["lib"]
32
32
 
33
33
  spec.add_development_dependency "bundler", "~> 1.16"
34
- spec.add_development_dependency "rake", "~> 13.0"
35
34
  spec.add_development_dependency "minitest", '~> 5.13.0'
36
35
  spec.add_development_dependency "nokogiri", '~> 1.10.7'
37
- spec.add_development_dependency "rubocop", '~> 0.77.0'
36
+ spec.add_development_dependency "rack-test", '~> 1.1.0'
38
37
 
38
+ spec.add_runtime_dependency "rake", "~> 13.0"
39
39
  spec.add_runtime_dependency 'rack', '~> 2.0.7'
40
40
  spec.add_runtime_dependency 'sequel', '~> 5.27.0'
41
41
  spec.add_runtime_dependency 'sqlite3', '~> 1.4.0'
42
- spec.add_runtime_dependency 'htmlbeautifier', '~> 1.3.1'
43
42
  end
data/lib/ezframe/auth.rb CHANGED
@@ -10,22 +10,21 @@ module Ezframe
10
10
  end
11
11
  Warden::Manager.serialize_from_session do |account|
12
12
  mylog "serialize_from: account = #{account}"
13
- inst = Auth.get(account)
13
+ inst = Auth.get(env['model'], account)
14
14
  mylog "inst = #{inst.inspect}"
15
15
  inst
16
16
  end
17
17
  Warden::Strategies.add(:mystrategy) do
18
18
  def valid?
19
- mylog "valid?"
19
+ # mylog "valid?"
20
20
  params["account"] || params["password"]
21
21
  end
22
22
 
23
23
  def authenticate!
24
24
  mylog "authenticate!: #{params}"
25
- if Auth.authenticate(params["account"], params["password"])
26
- success!(Auth.get(params["account"]))
25
+ if Auth.authenticate(env, params["account"], params["password"])
26
+ success!(Auth.get(env['model'], params["account"]))
27
27
  else
28
- # mylog "can i get env?: #{env}"
29
28
  env['x-rack.flash'].error = 'ユーザーが登録されていないか、パスワードが違っています。'
30
29
  fail!("authenticate failure")
31
30
  end
@@ -33,21 +32,25 @@ module Ezframe
33
32
  end
34
33
  end
35
34
 
36
- def get(account)
37
- new(account)
35
+ def get(model, account)
36
+ new(model, account)
38
37
  end
39
38
 
40
- def authenticate(account, pass)
41
- raise "model is not initialized" unless @model
42
- @user = @model.db.dataset(:user).where(account: account).first
39
+ def authenticate(env, account, pass)
40
+ model = env["model"]
41
+ raise "model is not initialized" unless model
42
+ @user = model.db.dataset(:user).where(account: account).first
43
43
  if @user
44
44
  mylog "Auth: authenticate: user=#{@user.inspect}"
45
45
  else
46
46
  mylog "authenticate: this user does not exist: #{account}"
47
47
  return nil
48
48
  end
49
+ mylog "env=#{env.inspect}"
50
+ env['rack.session'][:user] = @user[:id]
49
51
  password = @user[:password]
50
52
  @user.delete(:password)
53
+
51
54
  return nil if !pass || !password
52
55
  !!(password == pass)
53
56
  end
@@ -55,9 +58,9 @@ module Ezframe
55
58
 
56
59
  attr_accessor :account, :password, :model, :user, :id
57
60
 
58
- def initialize(account)
61
+ def initialize(model, account)
59
62
  self.account = account
60
- @user = Auth.model.db.dataset(:user).where(Sequel.or(account: account, id: account)).first
63
+ @user = model.db.dataset(:user).where(Sequel.or(account: account, id: account)).first
61
64
  unless @user
62
65
  mylog "Auth.initialize: This user does not exist: #{account}"
63
66
  end
@@ -37,7 +37,7 @@ module Ezframe
37
37
  end
38
38
 
39
39
  def [](table_name)
40
- @tables[table_name]
40
+ return @tables[table_name]
41
41
  end
42
42
 
43
43
  def each
@@ -46,7 +46,7 @@ module Ezframe
46
46
  end
47
47
 
48
48
  class ColumnSet
49
- attr_accessor :name, :parent
49
+ attr_accessor :name, :parent, :edit_keys, :view_keys
50
50
 
51
51
  def initialize(parent:, name: nil, columns: nil)
52
52
  @parent = parent
@@ -62,7 +62,7 @@ module Ezframe
62
62
  end
63
63
 
64
64
  def set(attr_a)
65
- @columns[:id] = IdType.new(key: "id", label: "ID", hidden: true, no_edit: true)
65
+ @columns[:id] = IdType.new(key: "id", label: "ID", no_edit: true)
66
66
  attr_a.each do |attributes|
67
67
  attr = attributes.clone
68
68
  col_key = attr[:key]
@@ -74,16 +74,16 @@ module Ezframe
74
74
  @columns[col_key.to_sym] = klass.new(attr)
75
75
  end
76
76
  end
77
- @columns[:created_at] = DateType.new(type: "date", key: "created_at", label: "生成日時", hidden: true, no_edit: true)
78
- @columns[:updated_at] = DateType.new(type: "date", key: "updated_at", label: "更新日時", hidden: true, no_edit: true)
77
+ @columns[:created_at] = DatetimeType.new(type: "datetime", key: "created_at", label: "生成日時", no_edit: true)
78
+ @columns[:updated_at] = DatetimeType.new(type: "datetime", key: "updated_at", label: "更新日時", no_edit: true)
79
79
  # mylog "set: #{@columns.inspect}"
80
80
  @columns.values.each {|col| col.parent = self }
81
- @columns
81
+ return @columns
82
82
  end
83
83
 
84
84
  def dataset
85
85
  # puts "dataset: #{@model.inspect}"
86
- @parent.model.db.dataset(@name)
86
+ return @parent.model.db.dataset(@name)
87
87
  end
88
88
 
89
89
  def set_from_db(id)
@@ -98,36 +98,53 @@ module Ezframe
98
98
  col_h.delete(:id)
99
99
  col_h.delete(:created_at)
100
100
  col_h[:updated_at] = Time.now
101
- p "save: #{col_h.inspect}"
101
+ mylog "save: #{col_h.inspect}"
102
102
  id = @columns[:id]
103
103
  if id.value.to_i > 0
104
104
  dataset.where(id: id.value).update(col_h)
105
105
  else
106
- dataset.insert(col_h)
106
+ return dataset.insert(col_h)
107
107
  end
108
108
  end
109
109
 
110
- def update(id, key, value)
111
- dataset.where(id: id).update(key => value)
112
- column = @columns[key.to_sym]
113
- column.value = value
114
- return column
110
+ def update(id, value_h)
111
+ values = {}
112
+ colkeys = @columns.keys
113
+ value_h.each do |k, v|
114
+ values[k] = v if colkeys.include?(k)
115
+ end
116
+ dataset.where(id: id).update(values)
117
+ set_values(values)
115
118
  end
116
119
 
117
120
  def values=(value_h)
118
121
  clear
119
- # puts "value_h=#{value_h.inspect}"
122
+ set_values(value_h)
123
+ end
124
+
125
+ def set_values(value_h)
126
+ return unless value_h
120
127
  value_h.each do |k, v|
121
- # puts "values=: k=#{k}, v=#{v}"
122
128
  col = @columns[k.to_sym]
123
- unless col
124
- mylog("no such column: #{k}")
125
- next
126
- end
129
+ next unless col
127
130
  col.value = v
128
131
  end
129
132
  end
130
133
 
134
+ def validate
135
+ clear_error
136
+ errors = []
137
+ @columns.values.each do |col|
138
+ err = col.validate
139
+ errors.push([ col.key, err ]) if err
140
+ end
141
+ return errors
142
+ end
143
+
144
+ def clear_error
145
+ @columns.values.each {|col| col.error = nil }
146
+ end
147
+
131
148
  def values
132
149
  @columns.map {|key, col| col.value}
133
150
  end
@@ -141,7 +158,7 @@ module Ezframe
141
158
  end
142
159
 
143
160
  def get_matrix(method_a)
144
- @columns.map do |_key, col|
161
+ return @columns.map do |_key, col|
145
162
  method_a.map { |method| col.send(method) }
146
163
  end
147
164
  end
@@ -149,24 +166,47 @@ module Ezframe
149
166
  def get_hash(method)
150
167
  res_h = {}
151
168
  @columns.map do |key, col|
152
- res_h[key] = col.send(method)
169
+ res_h[key.to_sym] = col.send(method)
153
170
  end
154
- res_h
171
+ return res_h
155
172
  end
156
173
 
157
174
  def [](col_key)
158
- @columns[col_key.to_sym]
175
+ return @columns[col_key.to_sym]
159
176
  end
160
177
 
161
178
  def form
162
- res = @columns.values.map do |coltype|
163
- coltype.form
179
+ if @edit_keys
180
+ return @edit_keys.map do |key|
181
+ col = @columns[key.to_sym]
182
+ unless col
183
+ mylog "[ERROR] @edit_keys has unknown column:name=#{@name}:key=#{key}"
184
+ next
185
+ end
186
+ col.form
187
+ end
188
+ else
189
+ return @columns.values.map {|coltype| coltype.form }
190
+ end
191
+ end
192
+
193
+ def view
194
+ if @view_keys
195
+ return @view_keys.map do |key|
196
+ col = @columns[key.to_sym]
197
+ unless col
198
+ mylog "[ERROR] @view_keys has unknown column:name=#{@name}:key=#{key}"
199
+ next
200
+ end
201
+ col.view
202
+ end
203
+ else
204
+ return @columns.values.map {|coltype| coltype.view }
164
205
  end
165
- res.compact
166
206
  end
167
207
 
168
208
  def hidden_form
169
- @columns.map do |colkey, coltype|
209
+ return @columns.map do |colkey, coltype|
170
210
  { tag: 'input', id: colkey, name: colkey, type: 'hidden', value: coltype.value }
171
211
  end
172
212
  end