ezframe 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ee9abffabef18607104a790bf9c044fd18022c1bb9c325d0b49c3919504da0e
|
4
|
+
data.tar.gz: 7c624b8735e2d081a73c8c5b771abdb3ca0a531a66d1e80ac953c4063dd237ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abf17a71fad66bdb9776346a155913664b78ebc9dfe4bc2fc94526340238423c7adf593650ed82e5e15ae052ecaa25e38a3a3803a68efa831d5cdf3d46478951
|
7
|
+
data.tar.gz: 4235b2a4e945845797e3cb41f27b675775598b8996952087701ca5ce678ef08abb28b44fb5f9b475a6281e16dd9845d77522824486b23f818ef773ea617e77ef
|
@@ -0,0 +1 @@
|
|
1
|
+
ezframe asset test
|
data/asset/js/ezframe.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// version. 2020?01?31?(?)
|
2
1
|
function add_event(obj) {
|
3
2
|
var elems = obj.querySelectorAll('[event]')
|
4
3
|
if (elems) {
|
@@ -49,9 +48,6 @@ function parse_event(event) {
|
|
49
48
|
}
|
50
49
|
}
|
51
50
|
}
|
52
|
-
/*if (!ev.url) {
|
53
|
-
ev.url = location.pathname
|
54
|
-
}*/
|
55
51
|
return ev
|
56
52
|
}
|
57
53
|
|
@@ -68,10 +64,9 @@ function execute_event(obj) {
|
|
68
64
|
}
|
69
65
|
return
|
70
66
|
case "set_global":
|
71
|
-
if (!window.ezframe) { window.ezframe = {} }
|
72
67
|
for(key in event) {
|
73
|
-
if ([ "command", "
|
74
|
-
window.
|
68
|
+
if ([ "command", "on", "url" ].indexOf(key) >= 0) { continue }
|
69
|
+
window.ez_global[key] = event[key]
|
75
70
|
}
|
76
71
|
// console.log("set_global:" + JSON.stringify(window.ezframe))
|
77
72
|
return
|
@@ -79,11 +74,45 @@ function execute_event(obj) {
|
|
79
74
|
console.log("redirect:" + event.url)
|
80
75
|
location.href = event.url
|
81
76
|
return
|
77
|
+
case "enable_datatable":
|
78
|
+
enable_datatable(event)
|
79
|
+
return
|
82
80
|
}
|
83
81
|
with_attr(event, obj)
|
84
82
|
post_values(event, obj)
|
85
83
|
}
|
86
84
|
|
85
|
+
function enable_datatable(event) {
|
86
|
+
// $("#enable_datatable").DataTable();
|
87
|
+
console.log("enable_datatable: target="+event.target)
|
88
|
+
// console.log($(tevent.arget))
|
89
|
+
var list_size = event.size || 5
|
90
|
+
$(event.target).DataTable({
|
91
|
+
lengthChange: false,
|
92
|
+
displayLength: parseInt(list_size),
|
93
|
+
columnDefs: [{ targets: '_all', className: 'ellipsis' }],
|
94
|
+
language: {
|
95
|
+
"decimal": ".",
|
96
|
+
"thousands": ",",
|
97
|
+
"sProcessing": "処理中...",
|
98
|
+
"sLengthMenu": "_MENU_ 件表示",
|
99
|
+
"sZeroRecords": "データはありません。",
|
100
|
+
"sInfo": " _TOTAL_ 件中 _START_ から _END_ まで表示",
|
101
|
+
"sInfoEmpty": " 0 件中 0 から 0 まで表示",
|
102
|
+
"sInfoFiltered": "(全 _MAX_ 件より抽出)",
|
103
|
+
"sInfoPostFix": "",
|
104
|
+
"sSearch": "検索:",
|
105
|
+
"sUrl": "",
|
106
|
+
"oPaginate": {
|
107
|
+
"sFirst": "<< 先頭",
|
108
|
+
"sPrevious": "< 前",
|
109
|
+
"sNext": "次 > ",
|
110
|
+
"sLast": "最終 >>"
|
111
|
+
}
|
112
|
+
}
|
113
|
+
})
|
114
|
+
}
|
115
|
+
|
87
116
|
function with_attr(event, obj) {
|
88
117
|
if (!event.with) {
|
89
118
|
return null
|
@@ -120,9 +149,8 @@ function post_values(event, obj) {
|
|
120
149
|
|
121
150
|
function manage_response(res, event, obj) {
|
122
151
|
var elem
|
123
|
-
|
152
|
+
console.log("manage_response: res="+JSON.stringify(res)+", event=" + JSON.stringify(event) +
|
124
153
|
", obj=" + JSON.stringify(obj))
|
125
|
-
*/
|
126
154
|
if (!res) { return }
|
127
155
|
if (Array.isArray(res)) {
|
128
156
|
for(var i = 0; i < res.length; i++) {
|
@@ -138,11 +166,7 @@ function exec_one_response(res) {
|
|
138
166
|
console.log("inject: " + res.inject)
|
139
167
|
elem = document.querySelector(res.inject)
|
140
168
|
if (elem) {
|
141
|
-
|
142
|
-
elem.innerHTML = res.body
|
143
|
-
} else {
|
144
|
-
elem.innerHTML = htmlgen(res.body)
|
145
|
-
}
|
169
|
+
elem.innerHTML = res.body.replace(/<br>/g, "\n")
|
146
170
|
add_event(elem)
|
147
171
|
} else {
|
148
172
|
console.log("no such element: "+res.inject)
|
@@ -175,12 +199,13 @@ function collect_form_values(obj) {
|
|
175
199
|
for (var i = 0; i < inputs.length; i++) {
|
176
200
|
var elem = inputs[i]
|
177
201
|
if (!elem.name) { continue }
|
178
|
-
console.log("name,value="+elem.name+","+elem.value)
|
202
|
+
// console.log("name,value="+elem.name+","+elem.value)
|
179
203
|
if ((elem.type == "checkbox" || elem.type == "radio") && !elem.checked) {
|
180
204
|
continue
|
181
205
|
}
|
182
206
|
var cur_value = res[elem.name]
|
183
|
-
var elem_value =
|
207
|
+
var elem_value = elem.value
|
208
|
+
elem_value = elem_value.replace(/\n/g, '<br>')
|
184
209
|
if (cur_value) {
|
185
210
|
if (Array.isArray(cur_value)) {
|
186
211
|
cur_value.push(elem_value)
|
@@ -194,10 +219,6 @@ function collect_form_values(obj) {
|
|
194
219
|
return res
|
195
220
|
}
|
196
221
|
|
197
|
-
function normalize(str) {
|
198
|
-
return str.replace(/^[\s| ]+|[\s| ]+$/g, '').trim()
|
199
|
-
}
|
200
|
-
|
201
222
|
function switch_hide(button) {
|
202
223
|
console.log("switch_hide")
|
203
224
|
var node = button
|
@@ -253,6 +274,14 @@ function register_hover_button(obj) {
|
|
253
274
|
}
|
254
275
|
}
|
255
276
|
|
277
|
+
|
256
278
|
document.addEventListener('DOMContentLoaded', function () {
|
279
|
+
if (!window.ez_global) { window.ez_global = {} }
|
280
|
+
add_event(document)
|
281
|
+
})
|
282
|
+
|
283
|
+
/*
|
284
|
+
$(document).ready(function () {
|
257
285
|
add_event(document)
|
258
286
|
})
|
287
|
+
*/
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#codnig: utf-8
|
3
|
+
|
4
|
+
=begin
|
5
|
+
|
6
|
+
column/*.ymlのチェックをする。
|
7
|
+
|
8
|
+
=end
|
9
|
+
require "ezframe"
|
10
|
+
|
11
|
+
# https://stackoverflow.com/questions/4911105/in-ruby-how-to-be-warned-of-duplicate-keys-in-hashes-when-loading-a-yaml-docume
|
12
|
+
def duplicate_keys(file_or_content)
|
13
|
+
yaml = file_or_content.is_a?(File) ? file_or_content.read : file_or_content
|
14
|
+
duplicate_keys = []
|
15
|
+
|
16
|
+
validator = ->(node, parent_path) do
|
17
|
+
if node.is_a?(Psych::Nodes::Mapping)
|
18
|
+
children = node.children.each_slice(2) # In a Mapping, every other child is the key node, the other is the value node.
|
19
|
+
duplicates = children.map { |key_node, _value_node| key_node }.group_by(&:value).select { |_value, nodes| nodes.size > 1 }
|
20
|
+
|
21
|
+
duplicates.each do |key, nodes|
|
22
|
+
duplicate_key = {
|
23
|
+
file: (file_or_content.path if file_or_content.is_a?(File)),
|
24
|
+
key: parent_path + [key],
|
25
|
+
occurrences: nodes.map { |occurrence| "line: #{occurrence.start_line + 1}" },
|
26
|
+
}.compact
|
27
|
+
|
28
|
+
duplicate_keys << duplicate_key
|
29
|
+
end
|
30
|
+
|
31
|
+
children.each { |key_node, value_node| validator.call(value_node, parent_path + [key_node ? key_node.value : nil].compact) }
|
32
|
+
else
|
33
|
+
node.children.to_a.each { |child| validator.call(child, parent_path) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
ast = Psych.parse_stream(yaml)
|
38
|
+
validator.call(ast, [])
|
39
|
+
|
40
|
+
duplicate_keys
|
41
|
+
end
|
42
|
+
|
43
|
+
Ezframe::Config.init
|
44
|
+
Dir["column/*.yml"].each do |file|
|
45
|
+
instr = File.read(file)
|
46
|
+
dup = duplicate_keys(instr)
|
47
|
+
if dup && dup.length > 0
|
48
|
+
puts "#{file}\n#{dup}"
|
49
|
+
end
|
50
|
+
yaml = YAML.load_file(file)
|
51
|
+
upper = Object.const_get("Ezframe")
|
52
|
+
yaml.each do |column|
|
53
|
+
type = column["type"]
|
54
|
+
unless type
|
55
|
+
puts "#{file}: type is not defined: key=#{column['key']}"
|
56
|
+
next
|
57
|
+
end
|
58
|
+
klass = "Ezframe::#{type.to_camel}Type"
|
59
|
+
unless upper.const_defined?(klass)
|
60
|
+
puts "#{file}: unknown type: key=#{column['key']}, type=#{type}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
data/exe/create_table
CHANGED
@@ -6,7 +6,10 @@ $:.push("lib")
|
|
6
6
|
require 'ezframe'
|
7
7
|
require 'sequel'
|
8
8
|
|
9
|
-
Ezframe
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
include Ezframe
|
10
|
+
|
11
|
+
Config.init
|
12
|
+
DB.init
|
13
|
+
ColumnSets.init
|
14
|
+
|
15
|
+
ColumnSets.create_tables
|
data/exe/dbmigrate
CHANGED
@@ -1,25 +1,68 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#coding: utf-8
|
3
3
|
require "ezframe"
|
4
|
-
|
5
4
|
include Ezframe
|
6
|
-
# get column set
|
7
|
-
Config.load_files("./config")
|
8
|
-
Model.init
|
9
|
-
$model = Model.get_clone
|
10
5
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
class DBInfo
|
7
|
+
class << self
|
8
|
+
def get_db_info(table_name)
|
9
|
+
typ = get_database_type(Config[:database])
|
10
|
+
case typ
|
11
|
+
when "postgresql"
|
12
|
+
return get_info_from_postgres(table_name)
|
13
|
+
when "sqlite"
|
14
|
+
return get_info_from_sqlite(table_name)
|
15
|
+
else
|
16
|
+
raise "unknown database"
|
17
|
+
end
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_info_from_postgres(table_name)
|
22
|
+
dbcol = {}
|
23
|
+
sql = "SELECT column_name,data_type FROM information_schema.columns WHERE table_name = '#{table_name}'"
|
24
|
+
begin
|
25
|
+
data_a = DB.sequel[sql].all
|
26
|
+
rescue
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
# puts data_a
|
30
|
+
data_a.each do |row|
|
31
|
+
dbcol[row[:column_name].to_s.to_sym] = normalize_dbtype(row[:data_type])
|
32
|
+
end
|
33
|
+
return dbcol
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_info_from_sqlite(table_name)
|
37
|
+
sql = "SELECT * from sqlite_master WHERE name = '#{table_name}';"
|
38
|
+
data = DB.sequel[sql].first
|
39
|
+
return nil unless data
|
40
|
+
sql = data[:sql]
|
41
|
+
return parse_create_sql(sql)
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_create_sql(sql)
|
45
|
+
sql.gsub(/CREATE TABLE \`\w+\` \(/, "")
|
46
|
+
column_a = sql.split(", ")
|
47
|
+
dbcol = {}
|
48
|
+
column_a.each do |line|
|
49
|
+
if line =~ /\`(\w+)\`\s(\w+)/
|
50
|
+
colkey, dbtype = $1, $2
|
51
|
+
dbcol[colkey.to_sym] = dbtype
|
52
|
+
end
|
53
|
+
end
|
54
|
+
return dbcol
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_database_type(config)
|
58
|
+
return config.split("://")[0]
|
59
|
+
end
|
16
60
|
end
|
17
|
-
return dbcol
|
18
61
|
end
|
19
62
|
|
20
63
|
def exec_sql(sql)
|
21
64
|
begin
|
22
|
-
|
65
|
+
DB.sequel.run(sql)
|
23
66
|
rescue => exception
|
24
67
|
p exception
|
25
68
|
end
|
@@ -44,7 +87,11 @@ end
|
|
44
87
|
|
45
88
|
def check_diff(column_set)
|
46
89
|
table_name = column_set.name
|
47
|
-
dbcols = get_db_info(table_name)
|
90
|
+
dbcols = DBInfo.get_db_info(table_name)
|
91
|
+
unless dbcols
|
92
|
+
ColumnSets.create_one_table(table_name, ColumnSets.get(table_name.to_sym))
|
93
|
+
return
|
94
|
+
end
|
48
95
|
column_set.each do |column|
|
49
96
|
next if %w[id updated_at created_at].include?(column.key.to_s)
|
50
97
|
dbtype = dbcols[column.key]
|
@@ -62,6 +109,10 @@ def check_diff(column_set)
|
|
62
109
|
end
|
63
110
|
end
|
64
111
|
|
65
|
-
|
112
|
+
Config.init
|
113
|
+
DB.init
|
114
|
+
ColumnSets.init
|
115
|
+
|
116
|
+
ColumnSets.each do |table_name, column_set|
|
66
117
|
check_diff(column_set)
|
67
118
|
end
|
data/ezframe.gemspec
CHANGED
@@ -30,16 +30,15 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
31
|
spec.require_paths = ["lib"]
|
32
32
|
|
33
|
-
spec.add_development_dependency "bundler",
|
34
|
-
spec.add_development_dependency "minitest", '
|
35
|
-
spec.add_development_dependency "nokogiri", '
|
36
|
-
spec.add_development_dependency "rack-test", '
|
37
|
-
spec.add_development_dependency "pry", '
|
38
|
-
spec.add_development_dependency "mailcatcher", '~> 0.7.1'
|
33
|
+
spec.add_development_dependency "bundler", '>= 1.16'
|
34
|
+
spec.add_development_dependency "minitest", '>= 5.13.0'
|
35
|
+
spec.add_development_dependency "nokogiri", '>= 1.10.7'
|
36
|
+
spec.add_development_dependency "rack-test", '>= 1.1.0'
|
37
|
+
spec.add_development_dependency "pry", '>= 0.12.2'
|
39
38
|
|
40
|
-
spec.add_runtime_dependency "rake",
|
41
|
-
spec.add_runtime_dependency 'rack', '
|
42
|
-
spec.add_runtime_dependency 'sequel', '
|
43
|
-
spec.add_runtime_dependency 'sqlite3', '
|
44
|
-
spec.add_runtime_dependency '
|
39
|
+
spec.add_runtime_dependency "rake", '>= 13.0'
|
40
|
+
spec.add_runtime_dependency 'rack', '>= 2.0.6'
|
41
|
+
spec.add_runtime_dependency 'sequel', '>= 5.27.0'
|
42
|
+
spec.add_runtime_dependency 'sqlite3', '>= 1.4.0'
|
43
|
+
spec.add_runtime_dependency 'bcrypt', '>= 3.1.13'
|
45
44
|
end
|
data/lib/ezframe.rb
CHANGED
@@ -4,9 +4,11 @@ require 'yaml'
|
|
4
4
|
require "sequel"
|
5
5
|
require "json"
|
6
6
|
require "nkf"
|
7
|
+
require "date"
|
7
8
|
|
8
9
|
require_relative 'ezframe/version'
|
9
10
|
require_relative 'ezframe/util'
|
11
|
+
require_relative 'ezframe/logger'
|
10
12
|
require_relative 'ezframe/config'
|
11
13
|
require_relative 'ezframe/controller'
|
12
14
|
require_relative 'ezframe/japanese_utils'
|
@@ -16,7 +18,6 @@ require_relative 'ezframe/database'
|
|
16
18
|
require_relative 'ezframe/ht'
|
17
19
|
require_relative 'ezframe/html'
|
18
20
|
require_relative 'ezframe/materialize'
|
19
|
-
require_relative 'ezframe/model'
|
20
21
|
require_relative 'ezframe/page_base'
|
21
22
|
require_relative 'ezframe/template'
|
22
23
|
require_relative 'ezframe/server'
|
data/lib/ezframe/auth.rb
CHANGED
@@ -1,75 +1,80 @@
|
|
1
1
|
module Ezframe
|
2
2
|
class Auth
|
3
3
|
class << self
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :user
|
5
5
|
|
6
|
-
def
|
6
|
+
def init
|
7
7
|
Warden::Manager.serialize_into_session do |auth|
|
8
|
-
|
8
|
+
# Logger.info "serialize_into: #{auth.inspect}"
|
9
9
|
auth.user[:id]
|
10
10
|
end
|
11
11
|
Warden::Manager.serialize_from_session do |account|
|
12
|
-
|
13
|
-
inst = Auth.get(
|
14
|
-
|
12
|
+
# Logger.info "serialize_from: account = #{account}"
|
13
|
+
inst = Auth.get(account)
|
14
|
+
# Logger.info "inst = #{inst.inspect}"
|
15
15
|
inst
|
16
16
|
end
|
17
17
|
Warden::Strategies.add(:mystrategy) do
|
18
18
|
def valid?
|
19
|
-
#
|
19
|
+
# Logger.info "valid?"
|
20
20
|
params["account"] || params["password"]
|
21
21
|
end
|
22
22
|
|
23
23
|
def authenticate!
|
24
|
-
|
24
|
+
Logger.info "Auth.authenticate: #{params}"
|
25
25
|
if Auth.authenticate(env, params["account"], params["password"])
|
26
|
-
success!(Auth.get(
|
26
|
+
success!(Auth.get(params["account"]))
|
27
27
|
else
|
28
|
-
|
29
|
-
fail!("authenticate failure")
|
28
|
+
fail!(Message[:login_failure])
|
30
29
|
end
|
31
30
|
end
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
def get(
|
36
|
-
new(
|
34
|
+
def get(account)
|
35
|
+
new(account)
|
37
36
|
end
|
38
37
|
|
39
38
|
def authenticate(env, account, pass)
|
40
|
-
|
41
|
-
|
42
|
-
@user =
|
39
|
+
Logger.debug("authenticate: #{env}")
|
40
|
+
auth_conf = Config[:auth]
|
41
|
+
@user = DB.dataset(auth_conf[:table]).where(auth_conf[:user].to_sym => account ).first
|
43
42
|
if @user
|
44
|
-
|
43
|
+
Logger.info "Auth: authenticate"
|
45
44
|
else
|
46
|
-
|
45
|
+
Logger.info "authenticate: this user does not exist: #{account}"
|
47
46
|
return nil
|
48
47
|
end
|
49
|
-
|
48
|
+
# Logger.info "env=#{env.inspect}"
|
50
49
|
env['rack.session'][:user] = @user[:id]
|
51
|
-
password = @user[:password]
|
50
|
+
password = @user[auth_conf[:password].to_sym]
|
51
|
+
Logger.debug("@user=#{@user}")
|
52
|
+
bcrypt = BCrypt::Password.new(password)
|
52
53
|
@user.delete(:password)
|
53
54
|
|
54
|
-
return nil if !pass || !password
|
55
|
-
|
55
|
+
return nil if !pass || pass.strip.empty? || !password || password.strip.empty?
|
56
|
+
# 生パスワード比較
|
57
|
+
# !!(password == pass)
|
58
|
+
return bcrypt == pass
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|
59
|
-
attr_accessor :account, :password, :
|
62
|
+
attr_accessor :account, :password, :user, :id
|
60
63
|
|
61
|
-
def initialize(
|
64
|
+
def initialize(account)
|
62
65
|
self.account = account
|
63
|
-
|
66
|
+
auth_conf = Config[:auth]
|
67
|
+
dataset = DB.dataset(auth_conf[:table])
|
64
68
|
if account.is_a?(Integer)
|
65
69
|
@user = dataset.where(id: account).first
|
66
70
|
else
|
67
|
-
@user = dataset.where(
|
71
|
+
@user = dataset.where(auth_conf[:user].to_sym => account).first
|
68
72
|
end
|
69
73
|
unless @user
|
70
|
-
|
74
|
+
Logger.error "Auth.initialize: This user does not exist: #{account}"
|
75
|
+
return
|
71
76
|
end
|
72
|
-
self.password = @user[:password]
|
77
|
+
self.password = @user[auth_conf[:password].to_sym]
|
73
78
|
@user.delete(:password)
|
74
79
|
end
|
75
80
|
end
|