editus 1.0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +94 -0
- data/Rakefile +18 -0
- data/app/controllers/editus/application_controller.rb +51 -0
- data/app/controllers/editus/home_controller.rb +121 -0
- data/app/helpers/editus/application_helper.rb +4 -0
- data/app/helpers/editus/home_helper.rb +18 -0
- data/app/models/editus/application_record.rb +5 -0
- data/app/views/editus/home/index.html.erb +79 -0
- data/app/views/editus/home/manual_update.html.erb +91 -0
- data/app/views/editus/home/scripts.html.erb +50 -0
- data/app/views/editus/home/validate.html.erb +39 -0
- data/app/views/editus/supports/bug.html.erb +18 -0
- data/app/views/layouts/editus/application.html.erb +186 -0
- data/config/routes.rb +11 -0
- data/lib/editus/actions.rb +51 -0
- data/lib/editus/client.rb +31 -0
- data/lib/editus/cop.rb +43 -0
- data/lib/editus/definition_proxy.rb +7 -0
- data/lib/editus/engine.rb +14 -0
- data/lib/editus/file.rb +42 -0
- data/lib/editus/proxy.rb +64 -0
- data/lib/editus/script.rb +77 -0
- data/lib/editus/version.rb +11 -0
- data/lib/editus.rb +109 -0
- data/lib/tasks/editus_tasks.rake +15 -0
- metadata +105 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
5
|
+
|
6
|
+
<title>Model updater</title>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
<%= csp_meta_tag %>
|
9
|
+
|
10
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
11
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
12
|
+
<link
|
13
|
+
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap"
|
14
|
+
rel="stylesheet"
|
15
|
+
/>
|
16
|
+
<link
|
17
|
+
rel="stylesheet"
|
18
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.5.0/semantic.min.css"
|
19
|
+
integrity="sha512-KXol4x3sVoO+8ZsWPFI/r5KBVB/ssCGB5tsv2nVOKwLg33wTFP3fmnXa47FdSVIshVTgsYk/1734xSk9aFIa4A=="
|
20
|
+
crossorigin="anonymous"
|
21
|
+
referrerpolicy="no-referrer"
|
22
|
+
/>
|
23
|
+
<script
|
24
|
+
src="https://code.jquery.com/jquery-3.1.1.min.js"
|
25
|
+
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
|
26
|
+
crossorigin="anonymous"
|
27
|
+
></script>
|
28
|
+
<script
|
29
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.5.0/semantic.min.js"
|
30
|
+
integrity="sha512-Xo0Jh8MsOn72LGV8kU5LsclG7SUzJsWGhXbWcYs2MAmChkQzwiW/yTQwdJ8w6UA9C6EVG18GHb/TrYpYCjyAQw=="
|
31
|
+
crossorigin="anonymous"
|
32
|
+
referrerpolicy="no-referrer"
|
33
|
+
></script>
|
34
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.23.0/ace.min.js" integrity="sha512-H7NE0Mw3ElsV/iE8dqG8hNkRkKkQ4C8l1i66QouYmeJZ0jRH/EvtMIOiIYlP6TxktZoExjy8Y+uvzTsJtwPdUQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
35
|
+
<style>
|
36
|
+
html,body {
|
37
|
+
overflow: auto;
|
38
|
+
}
|
39
|
+
html,
|
40
|
+
body,
|
41
|
+
.ui.text.container {
|
42
|
+
font-family: "Noto Sans", sans-serif;
|
43
|
+
}
|
44
|
+
.break-words{
|
45
|
+
overflow-wrap: break-word;
|
46
|
+
}
|
47
|
+
.main.container {
|
48
|
+
margin-top: 7em;
|
49
|
+
}
|
50
|
+
.flex{
|
51
|
+
display: flex;
|
52
|
+
}
|
53
|
+
items-center{
|
54
|
+
align-items: center;
|
55
|
+
}
|
56
|
+
.flex-column {
|
57
|
+
flex-direction: column;
|
58
|
+
}
|
59
|
+
.w-full {
|
60
|
+
width: 100% !important;
|
61
|
+
}
|
62
|
+
.w-3\/5 {
|
63
|
+
width: 60%;
|
64
|
+
}
|
65
|
+
.bg-neutral-300 {
|
66
|
+
background-color: rgb(212 212 212);
|
67
|
+
}
|
68
|
+
.rounded {
|
69
|
+
border-radius: 0.25rem;
|
70
|
+
}
|
71
|
+
.p-4 {
|
72
|
+
padding: 1rem;
|
73
|
+
}
|
74
|
+
.px-4 {
|
75
|
+
padding: 0 1rem;
|
76
|
+
}
|
77
|
+
.mb-4 {
|
78
|
+
margin-bottom: 1rem;
|
79
|
+
}
|
80
|
+
.ml-2 {
|
81
|
+
margin-left: 0.5rem;
|
82
|
+
}
|
83
|
+
.ml-4 {
|
84
|
+
margin-left: 1rem;
|
85
|
+
}
|
86
|
+
.mt-4 {
|
87
|
+
margin-top: 1rem;
|
88
|
+
}
|
89
|
+
.mx-4 {
|
90
|
+
margin-bottom: 1rem;
|
91
|
+
margin-top: 1rem;
|
92
|
+
}
|
93
|
+
.editor {
|
94
|
+
height: 420px;
|
95
|
+
}
|
96
|
+
pre {
|
97
|
+
white-space: pre-line;
|
98
|
+
}
|
99
|
+
.ui.cards>.orange.card, .ui.orange.card, .ui.orange.cards>.card {
|
100
|
+
box-shadow: 0 0 0 1px #d4d4d5, 0 0px 3px 1px #f2711c, 0 1px 3px 0 #d4d4d5;
|
101
|
+
}
|
102
|
+
.ui.cards>.orange.card:hover, .ui.orange.card:hover, .ui.orange.cards>.card:hover {
|
103
|
+
box-shadow: 0 0 0 1px #d4d4d5, 0 0px 5px 1px #f26202, 0 1px 3px 0 #bcbdbd;
|
104
|
+
}
|
105
|
+
.tablewrap {
|
106
|
+
position: relative
|
107
|
+
}
|
108
|
+
.ui.celled.table tr td, .ui.celled.table tr th {
|
109
|
+
word-break: break-all;
|
110
|
+
}
|
111
|
+
</style>
|
112
|
+
</head>
|
113
|
+
<body>
|
114
|
+
<div class="ui fixed inverted menu">
|
115
|
+
<div class="ui container">
|
116
|
+
<%= link_to 'Model Updater', root_path, class: "header item" %>
|
117
|
+
<%= link_to 'Home', root_path, class: "item" %>
|
118
|
+
<div class="ui simple dropdown item">
|
119
|
+
Menu <i class="dropdown icon"></i>
|
120
|
+
<div class="menu">
|
121
|
+
<%= link_to 'Scripts', scripts_path, class: "item" %>
|
122
|
+
<%= link_to 'Models', manual_update_path, class: "item" %>
|
123
|
+
</div>
|
124
|
+
</div>
|
125
|
+
</div>
|
126
|
+
</div>
|
127
|
+
|
128
|
+
<%= yield %>
|
129
|
+
|
130
|
+
|
131
|
+
<div class="ui modal confirmation">
|
132
|
+
<div class="header">Confirmation</div>
|
133
|
+
<div class="content">
|
134
|
+
<p>
|
135
|
+
These changes may cause data errors, do you still want to continue?
|
136
|
+
</p>
|
137
|
+
</div>
|
138
|
+
<div class="actions">
|
139
|
+
<div class="ui cancel button">Cancel</div>
|
140
|
+
<div class="ui ok red button">OK</div>
|
141
|
+
</div>
|
142
|
+
</div>
|
143
|
+
|
144
|
+
<script>
|
145
|
+
$("button.confirmation").on("click", function (e) {
|
146
|
+
$(".ui.confirmation.modal")
|
147
|
+
.modal({
|
148
|
+
onApprove: function () {
|
149
|
+
console.log($(e.currentTarget).data('method'))
|
150
|
+
switch ($(e.currentTarget).data('method')) {
|
151
|
+
case 'run':
|
152
|
+
$("#" + $(e.currentTarget).data('method')).submit()
|
153
|
+
break;
|
154
|
+
case 'undo':
|
155
|
+
console.log($(e.currentTarget).data('id'))
|
156
|
+
$("#" + $(e.currentTarget).data('id')).submit()
|
157
|
+
break;
|
158
|
+
default:
|
159
|
+
break;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
})
|
163
|
+
.modal("show");
|
164
|
+
});
|
165
|
+
|
166
|
+
$('section .ui.accordion').accordion();
|
167
|
+
|
168
|
+
$('.editor').each(function(_, ele) {
|
169
|
+
var editor = ace.edit(ele);
|
170
|
+
editor.setTheme("ace/theme/monokai");
|
171
|
+
editor.session.setMode("ace/mode/ruby");
|
172
|
+
editor.setReadOnly(true);
|
173
|
+
})
|
174
|
+
|
175
|
+
if (window.location.hash) {
|
176
|
+
$('#action-' + window.location.hash.replace('#', '')).addClass('orange')
|
177
|
+
}
|
178
|
+
|
179
|
+
$('a.action').on("click", function () {
|
180
|
+
setTimeout(() => {
|
181
|
+
$('#action-' + window.location.hash.replace('#', '')).addClass('orange')
|
182
|
+
}, 1000);
|
183
|
+
})
|
184
|
+
</script>
|
185
|
+
</body>
|
186
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Editus::Engine.routes.draw do
|
2
|
+
root "home#index"
|
3
|
+
|
4
|
+
get "manual_update", to: "home#manual_update"
|
5
|
+
get "scripts", to: "home#scripts"
|
6
|
+
post "/update", to: "home#update", as: :update
|
7
|
+
post "validate", to: "home#validate", as: :validate
|
8
|
+
|
9
|
+
post "scripts/:id/run", to: "home#run_script", as: :run
|
10
|
+
post "undo/:id", to: "home#undo", as: :undo
|
11
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Editus
|
2
|
+
class Actions
|
3
|
+
class << self
|
4
|
+
def all
|
5
|
+
con = Editus::FileLib.read(
|
6
|
+
Rails.root.join(Editus.configuration.actions_file_path)
|
7
|
+
)
|
8
|
+
json_parse(con)
|
9
|
+
end
|
10
|
+
|
11
|
+
def create action
|
12
|
+
actions = all.push(action)
|
13
|
+
path = Rails.root.join(Editus.configuration.actions_file_path)
|
14
|
+
Editus::FileLib.write(path, actions.to_json)
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove action
|
18
|
+
actions = all.push(action)
|
19
|
+
path = Rails.root.join(Editus.configuration.actions_file_path)
|
20
|
+
Editus::FileLib.write(path, actions.to_json)
|
21
|
+
end
|
22
|
+
|
23
|
+
def json_parse con
|
24
|
+
arr = JSON.parse(con)
|
25
|
+
arr.map do |haction|
|
26
|
+
Action.new(**haction.symbolize_keys)
|
27
|
+
end
|
28
|
+
rescue StandardError
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Action
|
35
|
+
attr_accessor :id, :user, :created_at, :model_id, :model_name, :changes, :type
|
36
|
+
|
37
|
+
def initialize **args
|
38
|
+
@id = args[:id] || SecureRandom.uuid
|
39
|
+
@created_at = args[:created_at] || Time.now.utc
|
40
|
+
@model_id = args[:model_id]
|
41
|
+
@model_name = args[:model_name]
|
42
|
+
@changes = args[:changes]
|
43
|
+
@type = args[:type]
|
44
|
+
@user = args[:user]
|
45
|
+
end
|
46
|
+
|
47
|
+
def save
|
48
|
+
Editus::Actions.create self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Editus
|
2
|
+
class Client
|
3
|
+
class << self
|
4
|
+
def models
|
5
|
+
all_models = ::ApplicationRecord.descendants.map(&:name)
|
6
|
+
if all_models.blank?
|
7
|
+
Rails.application.eager_load!
|
8
|
+
all_models = ::ApplicationRecord.descendants.map(&:name)
|
9
|
+
end
|
10
|
+
if valid_model_names.blank?
|
11
|
+
all_models
|
12
|
+
else
|
13
|
+
all_models & valid_model_names
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def model name
|
18
|
+
klass = Object.const_get(name)
|
19
|
+
if valid_model_names.present? && !valid_model_names.include?(klass.name)
|
20
|
+
raise Editus::InvalidModelError
|
21
|
+
end
|
22
|
+
|
23
|
+
Editus::Proxy.new(klass)
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_model_names
|
27
|
+
Editus::Cop.valid_model_names
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/editus/cop.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Editus
|
2
|
+
class Cop
|
3
|
+
def self.instance
|
4
|
+
@instance = new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.valid_model_names
|
8
|
+
instance.valid_model_names
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@models = Editus.configuration.models
|
13
|
+
@mapping = @models.map{|model| get_values(model)}.compact
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid_model_names
|
17
|
+
@valid_model_names ||= @mapping.map{|m| m[:name]}
|
18
|
+
end
|
19
|
+
|
20
|
+
def info model
|
21
|
+
result = if model.is_a?(String)
|
22
|
+
@mapping.find{|x| x[:name] == model}
|
23
|
+
elsif model.respond_to?(:name)
|
24
|
+
@mapping.find{|x| x[:name] == model.name}
|
25
|
+
end
|
26
|
+
|
27
|
+
result || {}
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def get_values model
|
33
|
+
return nil if model.blank?
|
34
|
+
return nil unless model.is_a?(String) || model.is_a?(Hash)
|
35
|
+
|
36
|
+
name = model.is_a?(String) ? model : model["name"]
|
37
|
+
fields = model.is_a?(Hash) ? model["fields"] : []
|
38
|
+
exclude_fields = model.is_a?(Hash) ? model["exclude_fields"] : []
|
39
|
+
|
40
|
+
{name: name, fields: fields, exclude_fields: exclude_fields}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/editus/file.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Editus
|
2
|
+
class FileLib
|
3
|
+
class << self
|
4
|
+
def instance
|
5
|
+
@instance ||= new
|
6
|
+
end
|
7
|
+
|
8
|
+
def read path
|
9
|
+
instance.create_file_if_not_exists(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def write path, content
|
13
|
+
instance.write_file_if_not_exists path, content
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_file_if_not_exists path, content
|
18
|
+
if File.exist?(path)
|
19
|
+
File.write(path, content)
|
20
|
+
else
|
21
|
+
FileUtils.mkdir_p(File.dirname(path))
|
22
|
+
File.open(path, "w") do |file|
|
23
|
+
file.puts content
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_file_if_not_exists path
|
29
|
+
if File.exist?(path)
|
30
|
+
File.read(path)
|
31
|
+
else
|
32
|
+
data = JSON.generate([])
|
33
|
+
FileUtils.mkdir_p(File.dirname(path))
|
34
|
+
File.open(path, "w") do |file|
|
35
|
+
file.puts data
|
36
|
+
end
|
37
|
+
|
38
|
+
data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/editus/proxy.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Editus
|
2
|
+
class Proxy
|
3
|
+
attr_reader :klass
|
4
|
+
|
5
|
+
def initialize klass
|
6
|
+
@klass = klass
|
7
|
+
end
|
8
|
+
|
9
|
+
def column_names
|
10
|
+
proxied_columns
|
11
|
+
end
|
12
|
+
|
13
|
+
def update_columns attributes; end
|
14
|
+
|
15
|
+
def find_by *args
|
16
|
+
record = klass.find_by(*args)
|
17
|
+
return record if record.blank?
|
18
|
+
|
19
|
+
RecordProxy.new(record)
|
20
|
+
end
|
21
|
+
|
22
|
+
def try *args
|
23
|
+
klass.try(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def proxied_columns
|
29
|
+
info = Editus::Cop.instance.info(klass)
|
30
|
+
all = cols
|
31
|
+
exclude_fields = info[:exclude_fields] || []
|
32
|
+
fields = info[:fields] ? (all & info[:fields]) : all
|
33
|
+
|
34
|
+
fields - %w[id] - exclude_fields
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing method, *args, &block
|
38
|
+
klass.try(method, *args, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def respond_to_missing? *args
|
42
|
+
klass.send(:respond_to_missing?, *args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def cols
|
46
|
+
klass.column_names
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class RecordProxy < Proxy
|
51
|
+
def update_columns attributes
|
52
|
+
update_fields = attributes.keys
|
53
|
+
raise Editus::UpdateFieldError if (update_fields - proxied_columns).present?
|
54
|
+
|
55
|
+
klass.update_columns attributes
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def cols
|
61
|
+
klass.class.column_names
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Editus
|
2
|
+
module Script
|
3
|
+
class << self
|
4
|
+
def define name, &block
|
5
|
+
Editus::Script::DSL.run(name, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def all
|
9
|
+
Editus::Script::Internal.scripts
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Internal
|
14
|
+
@scripts = {}
|
15
|
+
|
16
|
+
class << self
|
17
|
+
attr_reader :scripts
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find_or_create name
|
21
|
+
@scripts[name.to_sym] || @scripts[name.to_sym] = new(name.to_sym)
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :name, :title, :path, :proxy, :content
|
25
|
+
|
26
|
+
def initialize name = nil
|
27
|
+
@name = name
|
28
|
+
end
|
29
|
+
|
30
|
+
def up
|
31
|
+
content[/task\s.*up.*do.*\n[\s\S]*?\n\s*end/]
|
32
|
+
end
|
33
|
+
|
34
|
+
def down
|
35
|
+
content[/task\s.*down.*do.*\n[\s\S]*?\n\s*end/]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class DSL
|
40
|
+
TASKS = %w[up down].freeze
|
41
|
+
|
42
|
+
def self.run name, &block
|
43
|
+
new(name).instance_eval(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize name
|
47
|
+
@name = name
|
48
|
+
end
|
49
|
+
|
50
|
+
def task method, &block
|
51
|
+
return unless TASKS.include?(method.to_s)
|
52
|
+
|
53
|
+
internal = Internal.find_or_create @name
|
54
|
+
internal.proxy ||= Editus::DefinitionProxy.new(@name)
|
55
|
+
internal.proxy.define_singleton_method(method, &block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def title txt
|
59
|
+
internal = Internal.find_or_create @name
|
60
|
+
internal.title = txt
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Reader
|
65
|
+
def self.read path
|
66
|
+
return unless File.exist?(path)
|
67
|
+
|
68
|
+
load(path)
|
69
|
+
filename = File.basename(path, ".rb")
|
70
|
+
internal = Internal.find_or_create filename
|
71
|
+
internal.content = File.read(path)
|
72
|
+
internal.path = path
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Editus
|
2
|
+
VERSION = "1.0.0"
|
3
|
+
SUMMARY = "This application is a simple web interface integrated with an existing Ruby on Rails application. It allows users to directly edit models, run predefined scripts, and easily undo changes."
|
4
|
+
DESCRIPTION = <<~DOC
|
5
|
+
This application is a user-friendly web interface designed to work with a Ruby on Rails application. With a simple and intuitive web interface, users can conveniently access the features of the application.
|
6
|
+
|
7
|
+
One of the key features of this application is the ability to directly edit models. This enables users to make changes directly to the data without the need to learn and use complex tools. Through the web interface, users can access and modify the attributes of models with ease.
|
8
|
+
|
9
|
+
Additionally, the application provides the capability to run predefined scripts. This allows users to perform automated tasks or handle complex data processing through prebuilt scripts. Running these scripts via the web interface saves users time and effort compared to alternative methods.
|
10
|
+
DOC
|
11
|
+
end
|
data/lib/editus.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative "editus/actions"
|
2
|
+
require_relative "editus/client"
|
3
|
+
require_relative "editus/cop"
|
4
|
+
require_relative "editus/definition_proxy"
|
5
|
+
require_relative "editus/engine"
|
6
|
+
require_relative "editus/file"
|
7
|
+
require_relative "editus/proxy"
|
8
|
+
require_relative "editus/script"
|
9
|
+
require_relative "editus/version"
|
10
|
+
|
11
|
+
module Editus
|
12
|
+
class InvalidModelError < StandardError; end
|
13
|
+
class UpdateFieldError < StandardError; end
|
14
|
+
|
15
|
+
class Configuration
|
16
|
+
CONFIG_PATH = "config/editus.yml"
|
17
|
+
CONFIG_KEYS = %w[models auth actions_file_path]
|
18
|
+
INITIALIZER_FILE_PATH = "config/initializers/editus.rb"
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@table = {
|
22
|
+
models: [],
|
23
|
+
actions_file_path: "tmp/editus/actions.json"
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def [] name
|
28
|
+
@table[name.to_sym]
|
29
|
+
end
|
30
|
+
|
31
|
+
def []= name, value
|
32
|
+
name = name.to_sym
|
33
|
+
@table[name] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def respond_to_missing? mid, include_private = false
|
39
|
+
mid[/.*(?==\z)/m].present? || super
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing mid, *args
|
43
|
+
len = args.length
|
44
|
+
mname = mid[/.*(?==\z)/m]
|
45
|
+
if mname
|
46
|
+
if len != 1
|
47
|
+
raise ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
@table[mname.to_sym] = args[0]
|
51
|
+
elsif len.zero?
|
52
|
+
@table[mid]
|
53
|
+
else
|
54
|
+
begin
|
55
|
+
super
|
56
|
+
rescue NoMethodError => e
|
57
|
+
e.backtrace.shift
|
58
|
+
raise
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
attr_writer :configuration
|
66
|
+
attr_accessor :definition_file_paths
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.configuration
|
70
|
+
@configuration ||= Editus::Configuration.new
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.configure
|
74
|
+
yield(configuration)
|
75
|
+
end
|
76
|
+
|
77
|
+
self.definition_file_paths = %w[config/editus]
|
78
|
+
|
79
|
+
def self.find_definitions
|
80
|
+
absolute_definition_file_paths = definition_file_paths.map{|path| File.expand_path(path)}
|
81
|
+
|
82
|
+
absolute_definition_file_paths.uniq.each do |path|
|
83
|
+
next unless File.directory? path
|
84
|
+
|
85
|
+
Dir[File.join(path, "*.rb")].sort.each do |file|
|
86
|
+
Editus::Script::Reader.read(file)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.load_file_config
|
92
|
+
if File.exist?(Rails.root.join(Editus::Configuration::CONFIG_PATH))
|
93
|
+
yaml = File.read(Rails.root.join(Editus::Configuration::CONFIG_PATH))
|
94
|
+
config = YAML.safe_load(yaml)
|
95
|
+
|
96
|
+
configure do |c|
|
97
|
+
config.each do |key, value|
|
98
|
+
next unless Editus::Configuration::CONFIG_KEYS.include?(key)
|
99
|
+
|
100
|
+
c[key] = value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
else
|
104
|
+
false
|
105
|
+
end
|
106
|
+
rescue StandardError
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
namespace :editus do
|
2
|
+
desc "Generate config file for Editus"
|
3
|
+
task :install do
|
4
|
+
initializer_file_path = Rails.root.join(Editus::Configuration::INITIALIZER_FILE_PATH)
|
5
|
+
content = <<~DOC
|
6
|
+
# Editus.configure do |config|
|
7
|
+
# config.auth = [%w[user@example.com Pass@123456], %w[manager@example.com Pass@123456]]
|
8
|
+
# config.models = ["User", {name: "Admin", fields: %w[name], exclude_fields: %w[id]}]
|
9
|
+
# config.actions_file_path = "tmp/editus/actions.json"
|
10
|
+
# end
|
11
|
+
DOC
|
12
|
+
puts ">>> #{Editus::Configuration::INITIALIZER_FILE_PATH}"
|
13
|
+
File.write(initializer_file_path, content)
|
14
|
+
end
|
15
|
+
end
|