ezframe 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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